diff options
13 files changed, 858 insertions, 0 deletions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt new file mode 100644 index 000000000000..4e360f98723e --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt @@ -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") + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt new file mode 100644 index 000000000000..bd2e5756b4a9 --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt @@ -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)
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt new file mode 100644 index 000000000000..8daf4ca696bf --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt @@ -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) + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt new file mode 100644 index 000000000000..8eb182a9fa31 --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt @@ -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) + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt new file mode 100644 index 000000000000..28a914b96449 --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt @@ -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) + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt new file mode 100644 index 000000000000..ee018ecfd25a --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt @@ -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) + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt new file mode 100644 index 000000000000..74f1fd781a51 --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt @@ -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) + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml index 7f513b21957f..28422321f5b6 100644 --- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml @@ -130,5 +130,27 @@ <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </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> </manifest> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_notification.xml b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_notification.xml new file mode 100644 index 000000000000..09bd44c10865 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_notification.xml @@ -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> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml new file mode 100644 index 000000000000..78072006f681 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/notification_button.xml @@ -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> diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java index 18c95cf7bbff..e080709038ff 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java @@ -72,4 +72,14 @@ public class ActivityOptions { public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME = new ComponentName(FLICKER_APP_PACKAGE, 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"); } diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java new file mode 100644 index 000000000000..b31af385d363 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NotificationActivity.java @@ -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); + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java new file mode 100644 index 000000000000..6f94b74ccf41 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ShowWhenLockedActivity.java @@ -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); + } +} |