Merge changes from topic "update-flicker-annotation" into udc-qpr-dev

* changes:
  Add base test classes for SplitScreen scenario
  Update annotation package
This commit is contained in:
Pablo Gamito
2023-06-30 12:07:04 +00:00
committed by Android (Google) Code Review
30 changed files with 1584 additions and 19 deletions

View File

@@ -0,0 +1,67 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class CopyContentInSplit
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
private val textEditApp = SplitScreenUtils.getIme(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, textEditApp)
}
@Test
open fun copyContentInSplit() {
SplitScreenUtils.copyContentInSplit(instrumentation, device, primaryApp, textEditApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class DismissSplitScreenByDivider
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
@Test
open fun dismissSplitScreenByDivider() {
if (tapl.isTablet) {
SplitScreenUtils.dragDividerToDismissSplit(
device,
wmHelper,
dragToRight = false,
dragToBottom = true
)
} else {
SplitScreenUtils.dragDividerToDismissSplit(
device,
wmHelper,
dragToRight = true,
dragToBottom = true
)
}
wmHelper.StateSyncBuilder().withFullScreenApp(secondaryApp).waitForAndVerify()
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class DismissSplitScreenByGoHome
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
@Test
open fun dismissSplitScreenByGoHome() {
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class DragDividerToResize
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
@Test
open fun dragDividerToResize() {
SplitScreenUtils.dragDividerToResizeAndWait(device, wmHelper)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class EnterSplitScreenByDragFromAllApps
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
tapl.goHome()
primaryApp.launchViaIntent(wmHelper)
}
@Test
open fun enterSplitScreenByDragFromAllApps() {
tapl.launchedAppState.taskbar
.openAllApps()
.getAppIcon(secondaryApp.appName)
.dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class EnterSplitScreenByDragFromNotification
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
private val sendNotificationApp = SplitScreenUtils.getSendNotification(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
// Send a notification
sendNotificationApp.launchViaIntent(wmHelper)
sendNotificationApp.postNotification(wmHelper)
tapl.goHome()
primaryApp.launchViaIntent(wmHelper)
}
@Test
open fun enterSplitScreenByDragFromNotification() {
SplitScreenUtils.dragFromNotificationToSplit(instrumentation, device, wmHelper)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, sendNotificationApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
sendNotificationApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Assume
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class EnterSplitScreenByDragFromShortcut
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
Assume.assumeTrue(tapl.isTablet)
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
tapl.goHome()
SplitScreenUtils.createShortcutOnHotseatIfNotExist(tapl, secondaryApp.appName)
primaryApp.launchViaIntent(wmHelper)
}
@Test
open fun enterSplitScreenByDragFromShortcut() {
tapl.launchedAppState.taskbar
.getAppIcon(secondaryApp.appName)
.openDeepShortcutMenu()
.getMenuItem("Split Screen Secondary Activity")
.dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
// TODO: Do we want this check in here? Add to the other tests?
// flicker.splitScreenEntered(
// primaryApp,
// secondaryApp,
// fromOtherApp = false,
// appExistAtStart = false
// )
}
@After
fun teardwon() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class EnterSplitScreenByDragFromTaskbar
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
tapl.goHome()
SplitScreenUtils.createShortcutOnHotseatIfNotExist(tapl, secondaryApp.appName)
primaryApp.launchViaIntent(wmHelper)
}
@Test
open fun enterSplitScreenByDragFromTaskbar() {
tapl.launchedAppState.taskbar
.getAppIcon(secondaryApp.appName)
.dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class EnterSplitScreenFromOverview
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
wmHelper
.StateSyncBuilder()
.withAppTransitionIdle()
.withHomeActivityVisible()
.waitForAndVerify()
}
@Test
open fun enterSplitScreenFromOverview() {
SplitScreenUtils.splitFromOverview(tapl, device)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,422 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
import android.platform.test.rule.NavigationModeRule
import android.platform.test.rule.PressHomeRule
import android.platform.test.rule.UnlockScreenRule
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.common.traces.component.IComponentMatcher
import android.tools.common.traces.component.IComponentNameMatcher
import android.tools.device.apphelpers.MessagingAppHelper
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.rules.ChangeDisplayOrientationRule
import android.tools.device.flicker.rules.LaunchAppRule
import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
import android.view.InputDevice
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.test.platform.app.InstrumentationRegistry
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
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.NotificationAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import org.junit.Assert.assertNotNull
import org.junit.rules.RuleChain
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 val LONG_PRESS_TIME_MS = ViewConfiguration.getLongPressTimeout() * 2L
private val SPLIT_DECOR_MANAGER = ComponentNameMatcher("", "SplitDecorManager#")
private val notificationScrollerSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, NOTIFICATION_SCROLLER)
private val notificationContentSelector: BySelector
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)
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
fun testSetupRule(navigationMode: () -> NavBar, rotation: () -> Rotation): RuleChain {
return RuleChain.outerRule(UnlockScreenRule())
.around(
NavigationModeRule(
navigationMode().value,
/* changeNavigationModeAfterTest */ false
)
)
.around(
LaunchAppRule(MessagingAppHelper(instrumentation), clearCacheAfterParsing = false)
)
.around(RemoveAllTasksButHomeRule())
.around(
ChangeDisplayOrientationRule(
rotation(),
resetOrientationAfterTest = false,
clearCacheAfterParsing = false
)
)
.around(PressHomeRule())
}
fun getPrimary(instrumentation: Instrumentation): StandardAppHelper =
SimpleAppHelper(
instrumentation,
ActivityOptions.SplitScreen.Primary.LABEL,
ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent()
)
fun getSecondary(instrumentation: Instrumentation): StandardAppHelper =
SimpleAppHelper(
instrumentation,
ActivityOptions.SplitScreen.Secondary.LABEL,
ActivityOptions.SplitScreen.Secondary.COMPONENT.toFlickerComponent()
)
fun getNonResizeable(instrumentation: Instrumentation): NonResizeableAppHelper =
NonResizeableAppHelper(instrumentation)
fun getSendNotification(instrumentation: Instrumentation): NotificationAppHelper =
NotificationAppHelper(instrumentation)
fun getIme(instrumentation: Instrumentation): ImeAppHelper = ImeAppHelper(instrumentation)
fun waitForSplitComplete(
wmHelper: WindowManagerStateHelper,
primaryApp: IComponentMatcher,
secondaryApp: IComponentMatcher,
) {
wmHelper
.StateSyncBuilder()
.withWindowSurfaceAppeared(primaryApp)
.withWindowSurfaceAppeared(secondaryApp)
.withSplitDividerVisible()
.waitForAndVerify()
}
fun enterSplit(
wmHelper: WindowManagerStateHelper,
tapl: LauncherInstrumentation,
device: UiDevice,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
) {
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
splitFromOverview(tapl, device)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
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'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.
snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
t2.getVisibleBounds().left - t1.getVisibleBounds().left
}
snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
t1.getVisibleBounds().top - t2.getVisibleBounds().top
}
snapshots[0].click()
} else {
tapl.workspace
.switchToOverview()
.currentTask
.tapMenu()
.tapSplitMenuItem()
.currentTask
.open()
}
SystemClock.sleep(TIMEOUT_MS)
}
fun enterSplitViaIntent(
wmHelper: WindowManagerStateHelper,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
) {
val stringExtras =
mapOf(ActivityOptions.SplitScreen.Primary.EXTRA_LAUNCH_ADJACENT to "true")
primaryApp.launchViaIntent(wmHelper, null, null, stringExtras)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
fun dragFromNotificationToSplit(
instrumentation: Instrumentation,
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
val displayBounds =
wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
?: error("Display not found")
// Pull down the notifications
device.swipe(
displayBounds.centerX(),
5,
displayBounds.centerX(),
displayBounds.bottom,
50 /* steps */
)
SystemClock.sleep(TIMEOUT_MS)
// Find the target notification
val notificationScroller =
device.wait(Until.findObject(notificationScrollerSelector), TIMEOUT_MS)
?: error("Unable to find view $notificationScrollerSelector")
var notificationContent = notificationScroller.findObject(notificationContentSelector)
while (notificationContent == null) {
device.swipe(
displayBounds.centerX(),
displayBounds.centerY(),
displayBounds.centerX(),
displayBounds.centerY() - 150,
20 /* steps */
)
notificationContent = notificationScroller.findObject(notificationContentSelector)
}
// Drag to split
val dragStart = notificationContent.visibleCenter
val dragMiddle = Point(dragStart.x + 50, dragStart.y)
val dragEnd = Point(displayBounds.width / 4, displayBounds.width / 4)
val downTime = SystemClock.uptimeMillis()
touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, dragStart)
// It needs a horizontal movement to trigger the drag
touchMove(
instrumentation,
downTime,
SystemClock.uptimeMillis(),
DRAG_DURATION_MS,
dragStart,
dragMiddle
)
touchMove(
instrumentation,
downTime,
SystemClock.uptimeMillis(),
DRAG_DURATION_MS,
dragMiddle,
dragEnd
)
// Wait for a while to start splitting
SystemClock.sleep(TIMEOUT_MS)
touch(
instrumentation,
MotionEvent.ACTION_UP,
downTime,
SystemClock.uptimeMillis(),
GESTURE_STEP_MS,
dragEnd
)
SystemClock.sleep(TIMEOUT_MS)
}
fun touch(
instrumentation: Instrumentation,
action: Int,
downTime: Long,
eventTime: Long,
duration: Long,
point: Point
) {
val motionEvent =
MotionEvent.obtain(downTime, eventTime, action, point.x.toFloat(), point.y.toFloat(), 0)
motionEvent.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionEvent, true)
motionEvent.recycle()
SystemClock.sleep(duration)
}
fun touchMove(
instrumentation: Instrumentation,
downTime: Long,
eventTime: Long,
duration: Long,
from: Point,
to: Point
) {
val steps: Long = duration / GESTURE_STEP_MS
var currentTime = eventTime
var currentX = from.x.toFloat()
var currentY = from.y.toFloat()
val stepX = (to.x.toFloat() - from.x.toFloat()) / steps.toFloat()
val stepY = (to.y.toFloat() - from.y.toFloat()) / steps.toFloat()
for (i in 1..steps) {
val motionMove =
MotionEvent.obtain(
downTime,
currentTime,
MotionEvent.ACTION_MOVE,
currentX,
currentY,
0
)
motionMove.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionMove, true)
motionMove.recycle()
currentTime += GESTURE_STEP_MS
if (i == steps - 1) {
currentX = to.x.toFloat()
currentY = to.y.toFloat()
} else {
currentX += stepX
currentY += stepY
}
SystemClock.sleep(GESTURE_STEP_MS)
}
}
fun createShortcutOnHotseatIfNotExist(tapl: LauncherInstrumentation, appName: String) {
tapl.workspace.deleteAppIcon(tapl.workspace.getHotseatAppIcon(0))
val allApps = tapl.workspace.switchToAllApps()
allApps.freeze()
try {
allApps.getAppIcon(appName).dragToHotseat(0)
} finally {
allApps.unfreeze()
}
}
fun dragDividerToResizeAndWait(device: UiDevice, wmHelper: WindowManagerStateHelper) {
val displayBounds =
wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3), 200)
wmHelper
.StateSyncBuilder()
.withWindowSurfaceDisappeared(SPLIT_DECOR_MANAGER)
.waitForAndVerify()
}
fun dragDividerToDismissSplit(
device: UiDevice,
wmHelper: WindowManagerStateHelper,
dragToRight: Boolean,
dragToBottom: Boolean
) {
val displayBounds =
wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(
Point(
if (dragToRight) {
displayBounds.width * 4 / 5
} else {
displayBounds.width * 1 / 5
},
if (dragToBottom) {
displayBounds.height * 4 / 5
} else {
displayBounds.height * 1 / 5
}
)
)
}
fun doubleTapDividerToSwitch(device: UiDevice) {
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
val interval =
(ViewConfiguration.getDoubleTapTimeout() + ViewConfiguration.getDoubleTapMinTime()) / 2
dividerBar.click()
SystemClock.sleep(interval.toLong())
dividerBar.click()
}
fun copyContentInSplit(
instrumentation: Instrumentation,
device: UiDevice,
sourceApp: IComponentNameMatcher,
destinationApp: IComponentNameMatcher,
) {
// Copy text from sourceApp
val textView =
device.wait(
Until.findObject(By.res(sourceApp.packageName, "SplitScreenTest")),
TIMEOUT_MS
)
assertNotNull("Unable to find the TextView", textView)
textView.click(LONG_PRESS_TIME_MS)
val copyBtn = device.wait(Until.findObject(By.text("Copy")), TIMEOUT_MS)
assertNotNull("Unable to find the copy button", copyBtn)
copyBtn.click()
// Paste text to destinationApp
val editText =
device.wait(
Until.findObject(By.res(destinationApp.packageName, "plain_text_input")),
TIMEOUT_MS
)
assertNotNull("Unable to find the EditText", editText)
editText.click(LONG_PRESS_TIME_MS)
val pasteBtn = device.wait(Until.findObject(By.text("Paste")), TIMEOUT_MS)
assertNotNull("Unable to find the paste button", pasteBtn)
pasteBtn.click()
// Verify text
if (!textView.text.contentEquals(editText.text)) {
error("Fail to copy content in split")
}
}
}

View File

@@ -0,0 +1,151 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.graphics.Point
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.helpers.WindowUtils
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class SwitchAppByDoubleTapDivider
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
tapl.workspace.switchToOverview().dismissAllTasks()
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
}
@Test
open fun switchAppByDoubleTapDivider() {
SplitScreenUtils.doubleTapDividerToSwitch(device)
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
waitForLayersToSwitch(wmHelper)
waitForWindowsToSwitch(wmHelper)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
private fun waitForWindowsToSwitch(wmHelper: WindowManagerStateHelper) {
wmHelper
.StateSyncBuilder()
.add("appWindowsSwitched") {
val primaryAppWindow =
it.wmState.visibleWindows.firstOrNull { window ->
primaryApp.windowMatchesAnyOf(window)
}
?: return@add false
val secondaryAppWindow =
it.wmState.visibleWindows.firstOrNull { window ->
secondaryApp.windowMatchesAnyOf(window)
}
?: return@add false
if (isLandscape(rotation)) {
return@add if (isTablet()) {
secondaryAppWindow.frame.right <= primaryAppWindow.frame.left
} else {
primaryAppWindow.frame.right <= secondaryAppWindow.frame.left
}
} else {
return@add if (isTablet()) {
primaryAppWindow.frame.bottom <= secondaryAppWindow.frame.top
} else {
primaryAppWindow.frame.bottom <= secondaryAppWindow.frame.top
}
}
}
.waitForAndVerify()
}
private fun waitForLayersToSwitch(wmHelper: WindowManagerStateHelper) {
wmHelper
.StateSyncBuilder()
.add("appLayersSwitched") {
val primaryAppLayer =
it.layerState.visibleLayers.firstOrNull { window ->
primaryApp.layerMatchesAnyOf(window)
}
?: return@add false
val secondaryAppLayer =
it.layerState.visibleLayers.firstOrNull { window ->
secondaryApp.layerMatchesAnyOf(window)
}
?: return@add false
val primaryVisibleRegion = primaryAppLayer.visibleRegion?.bounds ?: return@add false
val secondaryVisibleRegion =
secondaryAppLayer.visibleRegion?.bounds ?: return@add false
if (isLandscape(rotation)) {
return@add if (isTablet()) {
secondaryVisibleRegion.right <= primaryVisibleRegion.left
} else {
primaryVisibleRegion.right <= secondaryVisibleRegion.left
}
} else {
return@add if (isTablet()) {
primaryVisibleRegion.bottom <= secondaryVisibleRegion.top
} else {
primaryVisibleRegion.bottom <= secondaryVisibleRegion.top
}
}
}
.waitForAndVerify()
}
private fun isLandscape(rotation: Rotation): Boolean {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return displayBounds.width > displayBounds.height
}
private fun isTablet(): Boolean {
val sizeDp: Point = device.displaySizeDp
val LARGE_SCREEN_DP_THRESHOLD = 600
return sizeDp.x >= LARGE_SCREEN_DP_THRESHOLD && sizeDp.y >= LARGE_SCREEN_DP_THRESHOLD
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class SwitchBackToSplitFromAnotherApp
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
private val thirdApp = SplitScreenUtils.getNonResizeable(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
thirdApp.launchViaIntent(wmHelper)
wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(thirdApp).waitForAndVerify()
}
@Test
open fun switchBackToSplitFromAnotherApp() {
tapl.launchedAppState.quickSwitchToPreviousApp()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class SwitchBackToSplitFromHome
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
@Test
open fun switchBackToSplitFromHome() {
tapl.workspace.quickSwitchToPreviousApp()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class SwitchBackToSplitFromRecent
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
@Test
open fun switchBackToSplitFromRecent() {
tapl.workspace.switchToOverview().currentTask.open()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class SwitchBetweenSplitPairs
@JvmOverloads
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
private val thirdApp = SplitScreenUtils.getIme(instrumentation)
private val fourthApp = SplitScreenUtils.getSendNotification(instrumentation)
@Rule
@JvmField
val testSetupRule = SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { rotation })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, device, thirdApp, fourthApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, thirdApp, fourthApp)
}
@Test
open fun switchBetweenSplitPairs() {
tapl.launchedAppState.quickSwitchToPreviousApp()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
thirdApp.exit(wmHelper)
fourthApp.exit(wmHelper)
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.service.splitscreen.scenarios
import android.app.Instrumentation
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@Ignore("Base Test Class")
abstract class UnlockKeyguardToSplitScreen {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
private val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
@Rule
@JvmField
val testSetupRule =
SplitScreenUtils.testSetupRule({ NavBar.MODE_GESTURAL }, { Rotation.ROTATION_0 })
@Before
fun setup() {
tapl.setEnableRotation(true)
tapl.setExpectedRotation(Rotation.ROTATION_0.value)
SplitScreenUtils.enterSplitViaIntent(wmHelper, primaryApp, secondaryApp)
}
@Test
open fun unlockKeyguardToSplitScreen() {
device.sleep()
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
device.wakeUp()
device.pressMenu()
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
@After
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
}

View File

@@ -114,13 +114,12 @@ internal object SplitScreenUtils {
}
fun enterSplitViaIntent(
wmHelper: WindowManagerStateHelper,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
wmHelper: WindowManagerStateHelper,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
) {
val stringExtras = mapOf(Primary.EXTRA_LAUNCH_ADJACENT to "true")
primaryApp.launchViaIntent(wmHelper, null, null,
stringExtras)
primaryApp.launchViaIntent(wmHelper, null, null, stringExtras)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}

View File

@@ -64,8 +64,7 @@ open class SwitchBetweenSplitPairsBenchmark(override val flicker: LegacyFlickerT
thisTransition(this)
}
@PlatinumTest(focusArea = "sysui")
@Presubmit @Test open fun cujCompleted() {}
@PlatinumTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() {}
companion object {
@Parameterized.Parameters(name = "{0}")

View File

@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.FlakyTest
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest

View File

@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.close
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.FlakyTest
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest

View File

@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.close
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest

View File

@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest

View File

@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.launch
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -21,7 +21,7 @@ import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory

View File

@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest

View File

@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.launch
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.common.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory