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:
Graciela Wissen Putri
2023-06-05 08:54:18 +00:00
committed by Graciela Putri
parent 9ce13dd292
commit 39fb1e0ce2
6 changed files with 238 additions and 19 deletions

View File

@@ -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)
}

View File

@@ -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()
}
}
}

View File

@@ -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)
)
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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.
*

View File

@@ -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
}
}