Merge "Add Flicker tests for launching app from Notification CUJ" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-04-09 01:02:07 +00:00
committed by Android (Google) Code Review
13 changed files with 858 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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