Merge "Add CUJ for quick switch between two split-pairs"

This commit is contained in:
TreeHugger Robot
2022-11-01 19:15:39 +00:00
committed by Android (Google) Code Review
13 changed files with 284 additions and 15 deletions

View File

@@ -21,6 +21,7 @@ package com.android.wm.shell.flicker
import com.android.server.wm.traces.common.ComponentNameMatcher
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher"
val APP_PAIR_SPLIT_DIVIDER_COMPONENT = ComponentNameMatcher("", "AppPairSplitDivider#")
val DOCKED_STACK_DIVIDER_COMPONENT = ComponentNameMatcher("", "DockedStackDivider#")
val SPLIT_SCREEN_DIVIDER_COMPONENT = ComponentNameMatcher("", "StageCoordinatorSplitDivider#")

View File

@@ -53,7 +53,7 @@ class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testS
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup { SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, textEditApp) }
setup { SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, textEditApp) }
transitions {
SplitScreenUtils.copyContentInSplit(
instrumentation,

View File

@@ -55,7 +55,7 @@ class DismissSplitScreenByDivider (testSpec: FlickerTestParameter) : SplitScreen
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
transitions {
if (tapl.isTablet) {

View File

@@ -52,7 +52,7 @@ class DismissSplitScreenByGoHome(
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
transitions {
tapl.goHome()

View File

@@ -56,7 +56,7 @@ class DragDividerToResize(testSpec: FlickerTestParameter) : SplitScreenBase(test
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
transitions {
SplitScreenUtils.dragDividerToResizeAndWait(device, wmHelper)

View File

@@ -34,7 +34,6 @@ import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
import com.android.wm.shell.flicker.splitScreenEntered
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,7 +54,6 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
get() = {
super.transition(this)
setup {
tapl.workspace.switchToOverview().dismissAllTasks()
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
@@ -65,7 +63,7 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
.waitForAndVerify()
}
transitions {
SplitScreenUtils.splitFromOverview(tapl)
SplitScreenUtils.splitFromOverview(tapl, device)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -34,6 +34,7 @@ abstract class SplitScreenBase(testSpec: FlickerTestParameter) : BaseTest(testSp
tapl.setEnableRotation(true)
setRotation(testSpec.startRotation)
tapl.setExpectedRotation(testSpec.startRotation)
tapl.workspace.switchToOverview().dismissAllTasks()
}
teardown {
primaryApp.exit(wmHelper)

View File

@@ -25,6 +25,7 @@ import android.view.ViewConfiguration
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.helpers.ImeAppHelper
@@ -38,13 +39,16 @@ import com.android.server.wm.traces.common.IComponentMatcher
import com.android.server.wm.traces.common.IComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import java.util.Collections
internal object SplitScreenUtils {
private const val TIMEOUT_MS = 3_000L
private const val DRAG_DURATION_MS = 1_000L
private const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
private const val DIVIDER_BAR = "docked_divider_handle"
private const val OVERVIEW_SNAPSHOT = "snapshot"
private const val GESTURE_STEP_MS = 16L
private const val LONG_PRESS_TIME_MS = 100L
private val SPLIT_DECOR_MANAGER = ComponentNameMatcher("", "SplitDecorManager#")
@@ -55,6 +59,8 @@ internal object SplitScreenUtils {
get() = By.text("Flicker Test Notification")
private val dividerBarSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, DIVIDER_BAR)
private val overviewSnapshotSelector: BySelector
get() = By.res(LAUNCHER_UI_PACKAGE_NAME, OVERVIEW_SNAPSHOT)
fun getPrimary(instrumentation: Instrumentation): StandardAppHelper =
SimpleAppHelper(
@@ -94,24 +100,39 @@ internal object SplitScreenUtils {
fun enterSplit(
wmHelper: WindowManagerStateHelper,
tapl: LauncherInstrumentation,
device: UiDevice,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
) {
tapl.workspace.switchToOverview().dismissAllTasks()
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
splitFromOverview(tapl)
splitFromOverview(tapl, device)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
fun splitFromOverview(tapl: LauncherInstrumentation) {
fun splitFromOverview(tapl: LauncherInstrumentation, device: UiDevice) {
// Note: The initial split position in landscape is different between tablet and phone.
// In landscape, tablet will let the first app split to right side, and phone will
// split to left side.
if (tapl.isTablet) {
tapl.workspace.switchToOverview().overviewActions.clickSplit().currentTask.open()
// TAPL's currentTask on tablet is sometimes not what we expected if the overview
// contains more than 3 task views. We need to use uiautomator directly to find the
// second task to split.
tapl.workspace.switchToOverview().overviewActions.clickSplit()
val snapshots = device.wait(Until.findObjects(overviewSnapshotSelector), TIMEOUT_MS)
if (snapshots == null || snapshots.size < 1) {
error("Fail to find a overview snapshot to split.")
}
// Find the second task in the upper right corner in split select mode by sorting
// 'left' in descending order and 'top' in ascending order.
Collections.sort(snapshots, { t1: UiObject2, t2: UiObject2 ->
t2.getVisibleBounds().left - t1.getVisibleBounds().left})
Collections.sort(snapshots, { t1: UiObject2, t2: UiObject2 ->
t1.getVisibleBounds().top - t2.getVisibleBounds().top})
snapshots[0].click()
} else {
tapl.workspace
.switchToOverview()

View File

@@ -56,7 +56,7 @@ class SwitchAppByDoubleTapDivider(testSpec: FlickerTestParameter) : SplitScreenB
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
transitions {
SplitScreenUtils.doubleTapDividerToSwitch(device)

View File

@@ -52,7 +52,7 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
thirdApp.launchViaIntent(wmHelper)
wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(thirdApp).waitForAndVerify()

View File

@@ -51,7 +51,7 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()

View File

@@ -51,7 +51,7 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()

View File

@@ -0,0 +1,248 @@
/*
* Copyright (C) 2022 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.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
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.dsl.FlickerBuilder
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.appWindowIsInvisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsSnapToDivider
import com.android.wm.shell.flicker.splitScreenDividerIsVisibleAtStart
import com.android.wm.shell.flicker.splitScreenDividerIsVisibleAtEnd
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 switch between two split pairs.
*
* To run this test: `atest WMShellFlickerTests:SwitchBetweenSplitPairs`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class SwitchBetweenSplitPairs(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
private val thirdApp = SplitScreenUtils.getIme(instrumentation)
private val fourthApp = SplitScreenUtils.getSendNotification(instrumentation)
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, thirdApp, fourthApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, thirdApp, fourthApp)
}
transitions {
tapl.launchedAppState.quickSwitchToPreviousApp()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
teardown {
thirdApp.exit(wmHelper)
fourthApp.exit(wmHelper)
}
}
@Postsubmit
@Test
fun cujCompleted() {
testSpec.appWindowIsVisibleAtStart(thirdApp)
testSpec.appWindowIsVisibleAtStart(fourthApp)
testSpec.splitScreenDividerIsVisibleAtStart()
testSpec.appWindowIsVisibleAtEnd(primaryApp)
testSpec.appWindowIsVisibleAtEnd(secondaryApp)
testSpec.appWindowIsInvisibleAtEnd(thirdApp)
testSpec.appWindowIsInvisibleAtEnd(fourthApp)
testSpec.splitScreenDividerIsVisibleAtEnd()
}
@Postsubmit
@Test
fun splitScreenDividerInvisibleAtMiddle() =
testSpec.assertLayers {
this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
.then()
.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
.then()
.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
}
@FlakyTest(bugId = 247095572)
@Test
fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
@FlakyTest(bugId = 247095572)
@Test
fun secondaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(secondaryApp)
@FlakyTest(bugId = 247095572)
@Test
fun thirdAppLayerBecomesInvisible() = testSpec.layerBecomesInvisible(thirdApp)
@FlakyTest(bugId = 247095572)
@Test
fun fourthAppLayerBecomesInvisible() = testSpec.layerBecomesInvisible(fourthApp)
@Postsubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() =
testSpec.splitAppLayerBoundsIsVisibleAtEnd(
primaryApp,
landscapePosLeft = tapl.isTablet,
portraitPosTop = false
)
@Postsubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() =
testSpec.splitAppLayerBoundsIsVisibleAtEnd(
secondaryApp,
landscapePosLeft = !tapl.isTablet,
portraitPosTop = true
)
@Postsubmit
@Test
fun thirdAppBoundsIsVisibleAtBegin() =
testSpec.assertLayersStart {
this.splitAppLayerBoundsSnapToDivider(
thirdApp,
landscapePosLeft = tapl.isTablet,
portraitPosTop = false,
testSpec.startRotation
)
}
@Postsubmit
@Test
fun fourthAppBoundsIsVisibleAtBegin() =
testSpec.assertLayersStart {
this.splitAppLayerBoundsSnapToDivider(
fourthApp,
landscapePosLeft = !tapl.isTablet,
portraitPosTop = true,
testSpec.startRotation
)
}
@Postsubmit
@Test
fun primaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(primaryApp)
@Postsubmit
@Test
fun secondaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp)
@Postsubmit
@Test
fun thirdAppWindowBecomesVisible() = testSpec.appWindowBecomesInvisible(thirdApp)
@Postsubmit
@Test
fun fourthAppWindowBecomesVisible() = testSpec.appWindowBecomesInvisible(fourthApp)
/** {@inheritDoc} */
@FlakyTest(bugId = 251268711)
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
@Presubmit
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() =
super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
override fun navBarLayerPositionAtStartAndEnd() =
super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Presubmit
@Test
override fun navBarWindowIsAlwaysVisible() =
super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@Presubmit
@Test
override fun statusBarLayerPositionAtStartAndEnd() =
super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Presubmit
@Test
override fun statusBarWindowIsAlwaysVisible() =
super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Presubmit
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() =
super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@Presubmit
@Test
override fun taskBarWindowIsAlwaysVisible() =
super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@FlakyTest
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
@Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}