Add RepositionFixedPortraitAppTest
Add helpers to reposition app and wait for app to move to expected bounds. Remove rotation configuration from BaseAppCompat and define in test instead. Fix: 283773197 Test: atest WMShellFlickerTests:RepositionFixedPortraitAppTest Change-Id: Ifae79ba244cc62419c9ea7b5b86fb9528055a3cc
This commit is contained in:
committed by
Graciela Putri
parent
9ce13dd292
commit
39fb1e0ce2
@@ -23,16 +23,15 @@ import android.tools.device.flicker.legacy.FlickerBuilder
|
||||
import android.tools.device.flicker.legacy.FlickerTest
|
||||
import com.android.server.wm.flicker.helpers.setRotation
|
||||
import com.android.server.wm.flicker.helpers.LetterboxAppHelper
|
||||
import android.tools.device.flicker.legacy.FlickerTestFactory
|
||||
import android.tools.device.flicker.legacy.IFlickerTestData
|
||||
import com.android.wm.shell.flicker.BaseTest
|
||||
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
|
||||
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
|
||||
import com.android.wm.shell.flicker.appWindowKeepVisible
|
||||
import com.android.wm.shell.flicker.layerKeepVisible
|
||||
import org.junit.After
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
|
||||
protected val context: Context = instrumentation.context
|
||||
@@ -58,12 +57,13 @@ abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
|
||||
cmdHelper = CommandsHelper.getInstance(instrumentation)
|
||||
Assume.assumeTrue(tapl.isTablet && isIgnoreOrientationRequest())
|
||||
letterboxStyle = mapLetterboxStyle()
|
||||
resetLetterboxStyle()
|
||||
setLetterboxEducationEnabled(false)
|
||||
}
|
||||
|
||||
@After
|
||||
fun after() {
|
||||
resetLetterboxEducationEnabled()
|
||||
resetLetterboxStyle()
|
||||
}
|
||||
|
||||
private fun mapLetterboxStyle(): HashMap<String, String> {
|
||||
@@ -87,9 +87,8 @@ abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
|
||||
return letterboxStyle
|
||||
}
|
||||
|
||||
private fun resetLetterboxEducationEnabled() {
|
||||
val enabled = getLetterboxStyle().getValue("Is education enabled")
|
||||
cmdHelper.executeShellCommand("wm set-letterbox-style --isEducationEnabled $enabled")
|
||||
private fun resetLetterboxStyle() {
|
||||
cmdHelper.executeShellCommand("wm reset-letterbox-style")
|
||||
}
|
||||
|
||||
private fun setLetterboxEducationEnabled(enabled: Boolean) {
|
||||
@@ -126,25 +125,21 @@ abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
|
||||
flicker.appWindowIsVisibleAtEnd(letterboxApp)
|
||||
}
|
||||
|
||||
fun assertLetterboxAppKeepVisible() {
|
||||
assertLetterboxAppWindowKeepVisible()
|
||||
assertLetterboxAppLayerKeepVisible()
|
||||
}
|
||||
|
||||
fun assertAppLetterboxedAtEnd() =
|
||||
flicker.assertLayersEnd { isVisible(ComponentNameMatcher.LETTERBOX) }
|
||||
|
||||
fun assertAppLetterboxedAtStart() =
|
||||
flicker.assertLayersStart { isVisible(ComponentNameMatcher.LETTERBOX) }
|
||||
|
||||
fun assertAppStaysLetterboxed() =
|
||||
flicker.assertLayers { isVisible(ComponentNameMatcher.LETTERBOX) }
|
||||
|
||||
fun assertLetterboxAppLayerKeepVisible() = flicker.layerKeepVisible(letterboxApp)
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestFactory.rotationTests] for configuring screen orientation and
|
||||
* navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTest> {
|
||||
return FlickerTestFactory.rotationTests()
|
||||
}
|
||||
}
|
||||
fun assertLetterboxAppWindowKeepVisible() = flicker.appWindowKeepVisible(letterboxApp)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.tools.common.traces.component.ComponentNameMatcher
|
||||
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
|
||||
import android.tools.device.flicker.legacy.FlickerBuilder
|
||||
import android.tools.device.flicker.legacy.FlickerTest
|
||||
import android.tools.device.flicker.legacy.FlickerTestFactory
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -90,4 +91,18 @@ class OpenAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flicker)
|
||||
.isInvisible(ComponentNameMatcher.ROTATION)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestFactory.rotationTests] for configuring screen orientation and
|
||||
* navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTest> {
|
||||
return FlickerTestFactory.rotationTests()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.appcompat
|
||||
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.tools.common.Rotation
|
||||
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
|
||||
import android.tools.device.flicker.legacy.FlickerBuilder
|
||||
import android.tools.device.flicker.legacy.FlickerTest
|
||||
import android.tools.device.flicker.legacy.FlickerTestFactory
|
||||
import android.tools.device.helpers.WindowUtils
|
||||
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test launching a fixed portrait letterboxed app in landscape and repositioning to the right.
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:RepositionFixedPortraitAppTest`
|
||||
* Actions:
|
||||
* ```
|
||||
* Launch a fixed portrait app in landscape to letterbox app
|
||||
* Double tap to the right to reposition app and wait for app to move
|
||||
* ```
|
||||
*
|
||||
* Notes:
|
||||
* ```
|
||||
* Some default assertions (e.g., nav bar, status bar and screen covered)
|
||||
* are inherited [BaseTest]
|
||||
* ```
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
class RepositionFixedPortraitAppTest(flicker: FlickerTest) : BaseAppCompat(flicker) {
|
||||
|
||||
val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation).bounds
|
||||
/** {@inheritDoc} */
|
||||
override val transition: FlickerBuilder.() -> Unit
|
||||
get() = {
|
||||
setup {
|
||||
setStartRotation()
|
||||
letterboxApp.launchViaIntent(wmHelper)
|
||||
}
|
||||
transitions {
|
||||
letterboxApp.repositionHorizontally(displayBounds, true)
|
||||
letterboxApp.waitForAppToMoveHorizontallyTo(wmHelper, displayBounds, true)
|
||||
}
|
||||
teardown {
|
||||
letterboxApp.repositionHorizontally(displayBounds, false)
|
||||
letterboxApp.exit(wmHelper)
|
||||
}
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun letterboxedAppHasRoundedCorners() = assertLetterboxAppAtEndHasRoundedCorners()
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun letterboxAppLayerKeepVisible() = assertLetterboxAppLayerKeepVisible()
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun appStaysLetterboxed() = assertAppStaysLetterboxed()
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun appKeepVisible() = assertLetterboxAppKeepVisible()
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
|
||||
* navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTest> {
|
||||
return FlickerTestFactory.nonRotationTests(
|
||||
supportedRotations = listOf(Rotation.ROTATION_90)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import android.platform.test.annotations.Postsubmit
|
||||
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
|
||||
import android.tools.device.flicker.legacy.FlickerBuilder
|
||||
import android.tools.device.flicker.legacy.FlickerTest
|
||||
import android.tools.device.flicker.legacy.FlickerTestFactory
|
||||
import android.tools.device.helpers.WindowUtils
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import org.junit.Test
|
||||
@@ -88,4 +89,18 @@ class RestartAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flick
|
||||
val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
|
||||
flicker.assertLayersEnd { visibleRegion(letterboxApp).coversAtMost(displayBounds) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestFactory.rotationTests] for configuring screen orientation and
|
||||
* navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTest> {
|
||||
return FlickerTestFactory.rotationTests()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,33 @@ public class GestureHelper {
|
||||
mUiAutomation = instrumentation.getUiAutomation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a series of {@link MotionEvent}s to simulate tapping.
|
||||
*
|
||||
* @param point coordinates of pointer to tap
|
||||
* @param times the number of times to tap
|
||||
*/
|
||||
public boolean tap(@NonNull Tuple point, int times) throws InterruptedException {
|
||||
PointerProperties ptrProp = getPointerProp(0, MotionEvent.TOOL_TYPE_FINGER);
|
||||
PointerCoords ptrCoord = getPointerCoord(point.x, point.y, 1, 1);
|
||||
|
||||
for (int i = 0; i <= times; i++) {
|
||||
// If already tapped, inject delay in between movements
|
||||
if (times > 0) {
|
||||
SystemClock.sleep(50L);
|
||||
}
|
||||
if (!primaryPointerDown(ptrProp, ptrCoord, SystemClock.uptimeMillis())) {
|
||||
return false;
|
||||
}
|
||||
// Delay before releasing tap
|
||||
SystemClock.sleep(100L);
|
||||
if (!primaryPointerUp(ptrProp, ptrCoord, SystemClock.uptimeMillis())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a series of {@link MotionEvent}s to simulate a drag gesture without pointer release.
|
||||
*
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.server.wm.flicker.helpers
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.tools.common.datatypes.Region
|
||||
import android.tools.common.datatypes.Rect
|
||||
import android.tools.common.traces.component.ComponentNameMatcher
|
||||
import android.tools.device.apphelpers.StandardAppHelper
|
||||
import android.tools.device.helpers.FIND_TIMEOUT
|
||||
@@ -36,6 +38,8 @@ constructor(
|
||||
ActivityOptions.NonResizeablePortraitActivity.COMPONENT.toFlickerComponent()
|
||||
) : StandardAppHelper(instr, launcherName, component) {
|
||||
|
||||
private val gestureHelper: GestureHelper = GestureHelper(mInstrumentation)
|
||||
|
||||
fun clickRestart(wmHelper: WindowManagerStateHelper) {
|
||||
val restartButton =
|
||||
uiDevice.wait(
|
||||
@@ -56,4 +60,64 @@ constructor(
|
||||
?: error("Restart dialog button not found")
|
||||
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
|
||||
}
|
||||
|
||||
fun repositionHorizontally(displayBounds: Rect, right: Boolean) {
|
||||
val x = if (right) displayBounds.right - BOUNDS_OFFSET else BOUNDS_OFFSET
|
||||
reposition(x.toFloat(), displayBounds.centerY().toFloat())
|
||||
}
|
||||
|
||||
fun repositionVertically(displayBounds: Rect, bottom: Boolean) {
|
||||
val y = if (bottom) displayBounds.bottom - BOUNDS_OFFSET else BOUNDS_OFFSET
|
||||
reposition(displayBounds.centerX().toFloat(), y.toFloat())
|
||||
}
|
||||
|
||||
private fun reposition(x: Float, y: Float) {
|
||||
val coords = GestureHelper.Tuple(x, y)
|
||||
require(gestureHelper.tap(coords, 2)) { "Failed to reposition letterbox app" }
|
||||
}
|
||||
|
||||
fun waitForAppToMoveHorizontallyTo(
|
||||
wmHelper: WindowManagerStateHelper,
|
||||
displayBounds: Rect,
|
||||
right: Boolean
|
||||
) {
|
||||
wmHelper.StateSyncBuilder().add("letterboxAppRepositioned") {
|
||||
val letterboxAppWindow = getWindowRegion(wmHelper)
|
||||
val appRegionBounds = letterboxAppWindow.bounds
|
||||
val appWidth = appRegionBounds.width
|
||||
return@add if (right) appRegionBounds.left == displayBounds.right - appWidth &&
|
||||
appRegionBounds.right == displayBounds.right
|
||||
else appRegionBounds.left == displayBounds.left &&
|
||||
appRegionBounds.right == displayBounds.left + appWidth
|
||||
}.waitForAndVerify()
|
||||
}
|
||||
|
||||
fun waitForAppToMoveVerticallyTo(
|
||||
wmHelper: WindowManagerStateHelper,
|
||||
displayBounds: Rect,
|
||||
navBarHeight: Int,
|
||||
bottom: Boolean
|
||||
) {
|
||||
wmHelper.StateSyncBuilder().add("letterboxAppRepositioned") {
|
||||
val letterboxAppWindow = getWindowRegion(wmHelper)
|
||||
val appRegionBounds = letterboxAppWindow.bounds
|
||||
val appHeight = appRegionBounds.height
|
||||
return@add if (bottom) appRegionBounds.bottom == displayBounds.bottom &&
|
||||
appRegionBounds.top == (displayBounds.bottom - appHeight + navBarHeight)
|
||||
else appRegionBounds.top == displayBounds.top &&
|
||||
appRegionBounds.bottom == displayBounds.top + appHeight
|
||||
}.waitForAndVerify()
|
||||
}
|
||||
|
||||
private fun getWindowRegion(wmHelper: WindowManagerStateHelper): Region {
|
||||
val windowRegion = wmHelper.getWindowRegion(this)
|
||||
require(!windowRegion.isEmpty) {
|
||||
"Unable to find letterbox app window in the current state"
|
||||
}
|
||||
return windowRegion
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BOUNDS_OFFSET: Int = 100
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user