Merge "Add Flicker tests for launching app from Notification CUJ" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
64d297bc49
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.helpers
|
||||||
|
|
||||||
|
import android.app.Instrumentation
|
||||||
|
import android.support.test.launcherhelper.ILauncherStrategy
|
||||||
|
import android.support.test.launcherhelper.LauncherStrategyFactory
|
||||||
|
import androidx.test.uiautomator.By
|
||||||
|
import androidx.test.uiautomator.UiDevice
|
||||||
|
import androidx.test.uiautomator.Until
|
||||||
|
import com.android.server.wm.flicker.testapp.ActivityOptions
|
||||||
|
import com.android.server.wm.traces.common.FlickerComponentName
|
||||||
|
import com.android.server.wm.traces.parser.toFlickerComponent
|
||||||
|
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
|
||||||
|
|
||||||
|
class NotificationAppHelper @JvmOverloads constructor(
|
||||||
|
instr: Instrumentation,
|
||||||
|
launcherName: String = ActivityOptions.NOTIFICATION_ACTIVITY_LAUNCHER_NAME,
|
||||||
|
component: FlickerComponentName =
|
||||||
|
ActivityOptions.NOTIFICATION_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
|
||||||
|
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
|
||||||
|
.getInstance(instr)
|
||||||
|
.launcherStrategy
|
||||||
|
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
|
||||||
|
fun postNotification(device: UiDevice, wmHelper: WindowManagerStateHelper) {
|
||||||
|
val button = device.wait(
|
||||||
|
Until.findObject(By.res(getPackage(), "post_notification")),
|
||||||
|
FIND_TIMEOUT)
|
||||||
|
|
||||||
|
require(button != null) {
|
||||||
|
"Post notification button not found, this usually happens when the device " +
|
||||||
|
"was left in an unknown state (e.g. in split screen)"
|
||||||
|
}
|
||||||
|
button.click()
|
||||||
|
|
||||||
|
device.wait(Until.findObject(By.text("Flicker Test Notification")), FIND_TIMEOUT)
|
||||||
|
?: error("Flicker Notification not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.helpers
|
||||||
|
|
||||||
|
import android.app.Instrumentation
|
||||||
|
import android.support.test.launcherhelper.ILauncherStrategy
|
||||||
|
import android.support.test.launcherhelper.LauncherStrategyFactory
|
||||||
|
import com.android.server.wm.flicker.testapp.ActivityOptions
|
||||||
|
import com.android.server.wm.traces.common.FlickerComponentName
|
||||||
|
import com.android.server.wm.traces.parser.toFlickerComponent
|
||||||
|
|
||||||
|
class ShowWhenLockedAppHelper @JvmOverloads constructor(
|
||||||
|
instr: Instrumentation,
|
||||||
|
launcherName: String = ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME,
|
||||||
|
component: FlickerComponentName =
|
||||||
|
ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
|
||||||
|
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
|
||||||
|
.getInstance(instr)
|
||||||
|
.launcherStrategy
|
||||||
|
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.launch
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import android.platform.test.annotations.RequiresDevice
|
||||||
|
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameter
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
||||||
|
import com.android.server.wm.flicker.annotation.Group1
|
||||||
|
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cold launching an app from a notification from the lock screen.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:OpenAppFromLockNotificationCold`
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Group1
|
||||||
|
@Postsubmit
|
||||||
|
open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter)
|
||||||
|
: OpenAppFromNotificationCold(testSpec) {
|
||||||
|
|
||||||
|
override val openingNotificationsFromLockScreen = true
|
||||||
|
|
||||||
|
override val transition: FlickerBuilder.() -> Unit
|
||||||
|
get() = {
|
||||||
|
// Needs to run at start of transition,
|
||||||
|
// so before the transition defined in super.transition
|
||||||
|
transitions {
|
||||||
|
device.wakeUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
super.transition(this)
|
||||||
|
|
||||||
|
// Needs to run at the end of the setup, so after the setup defined in super.transition
|
||||||
|
setup {
|
||||||
|
eachRun {
|
||||||
|
device.sleep()
|
||||||
|
wmHelper.waitFor("noAppWindowsOnTop") {
|
||||||
|
it.wmState.topVisibleAppWindow.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||||
|
* repetitions, screen orientation and navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams(): Collection<FlickerTestParameter> {
|
||||||
|
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
|
||||||
|
.getConfigNonRotationTests(repetitions = 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.launch
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import android.platform.test.annotations.RequiresDevice
|
||||||
|
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameter
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
||||||
|
import com.android.server.wm.flicker.annotation.Group1
|
||||||
|
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||||
|
import com.android.server.wm.traces.common.FlickerComponentName
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test warm launching an app from a notification from the lock screen.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:OpenAppFromLockNotificationWarm`
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Group1
|
||||||
|
@Postsubmit
|
||||||
|
open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter)
|
||||||
|
: OpenAppFromNotificationWarm(testSpec) {
|
||||||
|
|
||||||
|
override val openingNotificationsFromLockScreen = true
|
||||||
|
|
||||||
|
override val transition: FlickerBuilder.() -> Unit
|
||||||
|
get() = {
|
||||||
|
// Needs to run at start of transition,
|
||||||
|
// so before the transition defined in super.transition
|
||||||
|
transitions {
|
||||||
|
device.wakeUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
super.transition(this)
|
||||||
|
|
||||||
|
// Needs to run at the end of the setup, so after the setup defined in super.transition
|
||||||
|
setup {
|
||||||
|
eachRun {
|
||||||
|
device.sleep()
|
||||||
|
wmHelper.waitFor("noAppWindowsOnTop") {
|
||||||
|
it.wmState.topVisibleAppWindow.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that we start of with no top windows and then [testApp] becomes the first and
|
||||||
|
* only top window of the transition, with snapshot or splash screen windows optionally showing
|
||||||
|
* first.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
open fun appWindowBecomesFirstAndOnlyTopWindow() {
|
||||||
|
testSpec.assertWm {
|
||||||
|
this.hasNoVisibleAppWindow()
|
||||||
|
.then()
|
||||||
|
.isAppWindowOnTop(FlickerComponentName.SNAPSHOT, isOptional = true)
|
||||||
|
.then()
|
||||||
|
.isAppWindowOnTop(FlickerComponentName.SPLASH_SCREEN, isOptional = true)
|
||||||
|
.then()
|
||||||
|
.isAppWindowOnTop(testApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the screen is locked.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun screenLockedStart() {
|
||||||
|
testSpec.assertLayersStart {
|
||||||
|
isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||||
|
* repetitions, screen orientation and navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams(): Collection<FlickerTestParameter> {
|
||||||
|
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
|
||||||
|
.getConfigNonRotationTests(repetitions = 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.launch
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import android.platform.test.annotations.RequiresDevice
|
||||||
|
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameter
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
||||||
|
import com.android.server.wm.flicker.annotation.Group1
|
||||||
|
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||||
|
import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
|
||||||
|
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
|
||||||
|
import com.android.server.wm.traces.common.FlickerComponentName
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cold launching an app from a notification from the lock screen when there is an app
|
||||||
|
* overlaid on the lock screen.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:OpenAppFromLockNotificationWithLockOverlayApp`
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Group1
|
||||||
|
@Postsubmit
|
||||||
|
class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParameter)
|
||||||
|
: OpenAppFromLockNotificationCold(testSpec) {
|
||||||
|
private val showWhenLockedApp: ShowWhenLockedAppHelper =
|
||||||
|
ShowWhenLockedAppHelper(instrumentation)
|
||||||
|
|
||||||
|
// Although we are technically still locked here, the overlay app means we should open the
|
||||||
|
// notification shade as if we were unlocked.
|
||||||
|
override val openingNotificationsFromLockScreen = false
|
||||||
|
|
||||||
|
override val transition: FlickerBuilder.() -> Unit
|
||||||
|
get() = {
|
||||||
|
super.transition(this)
|
||||||
|
|
||||||
|
setup {
|
||||||
|
eachRun {
|
||||||
|
device.wakeUpAndGoToHomeScreen()
|
||||||
|
|
||||||
|
// Launch an activity that is shown when the device is locked
|
||||||
|
showWhenLockedApp.launchViaIntent(wmHelper)
|
||||||
|
wmHelper.waitForFullScreenApp(showWhenLockedApp.component)
|
||||||
|
|
||||||
|
device.sleep()
|
||||||
|
wmHelper.waitFor("noAppWindowsOnTop") {
|
||||||
|
it.wmState.topVisibleAppWindow.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown {
|
||||||
|
test {
|
||||||
|
showWhenLockedApp.exit(wmHelper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun showWhenLockedAppWindowBecomesVisible() {
|
||||||
|
testSpec.assertWm {
|
||||||
|
this.hasNoVisibleAppWindow()
|
||||||
|
.then()
|
||||||
|
.isAppWindowOnTop(FlickerComponentName.SNAPSHOT, isOptional = true)
|
||||||
|
.then()
|
||||||
|
.isAppWindowOnTop(showWhenLockedApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun showWhenLockedAppLayerBecomesVisible() {
|
||||||
|
testSpec.assertLayers {
|
||||||
|
this.isInvisible(showWhenLockedApp.component)
|
||||||
|
.then()
|
||||||
|
.isVisible(FlickerComponentName.SNAPSHOT, isOptional = true)
|
||||||
|
.then()
|
||||||
|
.isVisible(showWhenLockedApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||||
|
* repetitions, screen orientation and navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams(): Collection<FlickerTestParameter> {
|
||||||
|
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
|
||||||
|
.getConfigNonRotationTests(repetitions = 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.launch
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import android.platform.test.annotations.RequiresDevice
|
||||||
|
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameter
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
||||||
|
import com.android.server.wm.flicker.annotation.Group1
|
||||||
|
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cold launching an app from a notification.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:OpenAppFromNotificationCold`
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Group1
|
||||||
|
@Postsubmit
|
||||||
|
open class OpenAppFromNotificationCold(testSpec: FlickerTestParameter)
|
||||||
|
: OpenAppFromNotificationWarm(testSpec) {
|
||||||
|
override val transition: FlickerBuilder.() -> Unit
|
||||||
|
get() = {
|
||||||
|
super.transition(this)
|
||||||
|
|
||||||
|
setup {
|
||||||
|
eachRun {
|
||||||
|
// Close the app that posted the notification to trigger a cold start next time
|
||||||
|
// it is open - can't just kill it because that would remove the notification.
|
||||||
|
taplInstrumentation.goHome()
|
||||||
|
taplInstrumentation.workspace.switchToOverview()
|
||||||
|
taplInstrumentation.overview.dismissAllTasks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||||
|
* repetitions, screen orientation and navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams(): Collection<FlickerTestParameter> {
|
||||||
|
return com.android.server.wm.flicker.FlickerTestParameterFactory.getInstance()
|
||||||
|
.getConfigNonRotationTests(repetitions = 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.launch
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import android.platform.test.annotations.RequiresDevice
|
||||||
|
import android.view.WindowInsets
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.test.uiautomator.By
|
||||||
|
import androidx.test.uiautomator.Until
|
||||||
|
import com.android.launcher3.tapl.LauncherInstrumentation
|
||||||
|
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameter
|
||||||
|
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
||||||
|
import com.android.server.wm.flicker.annotation.Group1
|
||||||
|
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||||
|
import com.android.server.wm.flicker.helpers.NotificationAppHelper
|
||||||
|
import com.android.server.wm.flicker.helpers.setRotation
|
||||||
|
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cold launching an app from a notification.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:OpenAppFromNotificationWarm`
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
@Group1
|
||||||
|
@Postsubmit
|
||||||
|
open class OpenAppFromNotificationWarm(testSpec: FlickerTestParameter)
|
||||||
|
: OpenAppTransition(testSpec) {
|
||||||
|
protected val taplInstrumentation = LauncherInstrumentation()
|
||||||
|
|
||||||
|
override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
|
||||||
|
|
||||||
|
open val openingNotificationsFromLockScreen = false
|
||||||
|
|
||||||
|
override val transition: FlickerBuilder.() -> Unit
|
||||||
|
get() = {
|
||||||
|
setup {
|
||||||
|
test {
|
||||||
|
device.wakeUpAndGoToHomeScreen()
|
||||||
|
this.setRotation(testSpec.startRotation)
|
||||||
|
}
|
||||||
|
eachRun {
|
||||||
|
testApp.launchViaIntent(wmHelper)
|
||||||
|
wmHelper.waitForFullScreenApp(testApp.component)
|
||||||
|
testApp.postNotification(device, wmHelper)
|
||||||
|
device.pressHome()
|
||||||
|
wmHelper.waitForAppTransitionIdle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions {
|
||||||
|
var startY = 10
|
||||||
|
var endY = 3 * device.displayHeight / 4
|
||||||
|
var steps = 25
|
||||||
|
if (openingNotificationsFromLockScreen) {
|
||||||
|
val wm = instrumentation.context.getSystemService(WindowManager::class.java)
|
||||||
|
val metricInsets = wm.currentWindowMetrics.windowInsets
|
||||||
|
val insets = metricInsets.getInsetsIgnoringVisibility(
|
||||||
|
WindowInsets.Type.statusBars()
|
||||||
|
or WindowInsets.Type.displayCutout())
|
||||||
|
|
||||||
|
startY = insets.top + 100
|
||||||
|
endY = device.displayHeight / 2
|
||||||
|
steps = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swipe down to show the notification shade
|
||||||
|
val x = device.displayWidth / 2
|
||||||
|
device.swipe(x, startY, x, endY, steps)
|
||||||
|
device.waitForIdle(2000)
|
||||||
|
instrumentation.uiAutomation.syncInputTransactions()
|
||||||
|
|
||||||
|
// Launch the activity by clicking the notification
|
||||||
|
val notification = device.wait(Until.findObject(
|
||||||
|
By.text("Flicker Test Notification")), 2000L)
|
||||||
|
notification?.click() ?: error("Notification not found")
|
||||||
|
instrumentation.uiAutomation.syncInputTransactions()
|
||||||
|
|
||||||
|
// Wait for the app to launch
|
||||||
|
wmHelper.waitForFullScreenApp(testApp.component)
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown {
|
||||||
|
test {
|
||||||
|
testApp.exit(wmHelper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun statusBarLayerIsVisible() = super.statusBarLayerIsVisible()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
|
||||||
|
super.visibleLayersShownMoreThanOneConsecutiveEntry()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun notificationAppWindowVisibleAtEnd() {
|
||||||
|
testSpec.assertWmEnd {
|
||||||
|
this.isAppWindowVisible(testApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun notificationAppWindowOnTopAtEnd() {
|
||||||
|
testSpec.assertWmEnd {
|
||||||
|
this.isAppWindowOnTop(testApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Postsubmit
|
||||||
|
fun notificationAppLayerVisibleAtEnd() {
|
||||||
|
testSpec.assertLayersEnd {
|
||||||
|
this.isVisible(testApp.component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||||
|
* repetitions, screen orientation and navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams(): Collection<FlickerTestParameter> {
|
||||||
|
return FlickerTestParameterFactory.getInstance()
|
||||||
|
.getConfigNonRotationTests(repetitions = 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -130,5 +130,27 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".ShowWhenLockedActivity"
|
||||||
|
android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
|
||||||
|
android:theme="@style/CutoutShortEdges"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:label="ShowWhenLockedActivity"
|
||||||
|
android:showWhenLocked="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".NotificationActivity"
|
||||||
|
android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
|
||||||
|
android:theme="@style/CutoutShortEdges"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2018 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/holo_orange_light">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/post_notification"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Post Notification" />
|
||||||
|
</LinearLayout>
|
||||||
@@ -72,4 +72,14 @@ public class ActivityOptions {
|
|||||||
public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME =
|
public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME =
|
||||||
new ComponentName(FLICKER_APP_PACKAGE,
|
new ComponentName(FLICKER_APP_PACKAGE,
|
||||||
FLICKER_APP_PACKAGE + ".ImeEditorPopupDialogActivity");
|
FLICKER_APP_PACKAGE + ".ImeEditorPopupDialogActivity");
|
||||||
|
|
||||||
|
public static final String SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME = "ShowWhenLockedApp";
|
||||||
|
public static final ComponentName SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME =
|
||||||
|
new ComponentName(FLICKER_APP_PACKAGE,
|
||||||
|
FLICKER_APP_PACKAGE + ".ShowWhenLockedActivity");
|
||||||
|
|
||||||
|
public static final String NOTIFICATION_ACTIVITY_LAUNCHER_NAME = "NotificationApp";
|
||||||
|
public static final ComponentName NOTIFICATION_ACTIVITY_COMPONENT_NAME =
|
||||||
|
new ComponentName(FLICKER_APP_PACKAGE,
|
||||||
|
FLICKER_APP_PACKAGE + ".NotificationActivity");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.testapp;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.TaskStackBuilder;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class NotificationActivity extends Activity {
|
||||||
|
private static final String CHANNEL_ID = "notification_channel";
|
||||||
|
private static final int NOTIFICATION_ID = 1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
WindowManager.LayoutParams p = getWindow().getAttributes();
|
||||||
|
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
|
||||||
|
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||||
|
getWindow().setAttributes(p);
|
||||||
|
setContentView(R.layout.notification_button);
|
||||||
|
|
||||||
|
Button button = findViewById(R.id.post_notification);
|
||||||
|
button.setOnClickListener(v -> postNotification());
|
||||||
|
|
||||||
|
createNotificationChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postNotification() {
|
||||||
|
Intent resultIntent = new Intent(this, NotificationActivity.class);
|
||||||
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||||
|
stackBuilder.addNextIntentWithParentStack(resultIntent);
|
||||||
|
PendingIntent resultPendingIntent =
|
||||||
|
stackBuilder.getPendingIntent(0,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
|
||||||
|
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setContentTitle("Flicker Test Notification")
|
||||||
|
.setContentText("Flicker Test Notification")
|
||||||
|
// Set the intent that will fire when the user taps the notification
|
||||||
|
.setContentIntent(resultPendingIntent)
|
||||||
|
.setAutoCancel(true);
|
||||||
|
|
||||||
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
|
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotificationChannel() {
|
||||||
|
CharSequence name = "channel_name";
|
||||||
|
String description = "channel_description";
|
||||||
|
int importance = NotificationManager.IMPORTANCE_HIGH;
|
||||||
|
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
|
||||||
|
channel.setDescription(description);
|
||||||
|
// Register the channel with the system; you can't change the importance
|
||||||
|
// or other notification behaviors after this
|
||||||
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.testapp;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
public class ShowWhenLockedActivity extends Activity {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
WindowManager.LayoutParams p = getWindow().getAttributes();
|
||||||
|
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
|
||||||
|
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||||
|
getWindow().setAttributes(p);
|
||||||
|
setContentView(R.layout.activity_simple);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user