1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm.flicker.notification
18 
19 import android.platform.systemui_tapl.controller.NotificationIdentity
20 import android.platform.systemui_tapl.ui.Root
21 import android.platform.test.annotations.Postsubmit
22 import android.platform.test.annotations.Presubmit
23 import android.platform.test.rule.DisableNotificationCooldownSettingRule
24 import android.tools.flicker.junit.FlickerParametersRunnerFactory
25 import android.tools.flicker.legacy.FlickerBuilder
26 import android.tools.flicker.legacy.FlickerTestData
27 import android.tools.flicker.legacy.LegacyFlickerTest
28 import android.tools.flicker.legacy.LegacyFlickerTestFactory
29 import android.tools.helpers.wakeUpAndGoToHomeScreen
30 import android.tools.traces.component.ComponentNameMatcher
31 import android.view.WindowInsets
32 import android.view.WindowManager
33 import com.android.server.wm.flicker.helpers.NotificationAppHelper
34 import com.android.server.wm.flicker.helpers.setRotation
35 import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
36 import com.android.server.wm.flicker.navBarLayerPositionAtEnd
37 import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
38 import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
39 import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
40 import org.junit.Assume
41 import org.junit.ClassRule
42 import org.junit.FixMethodOrder
43 import org.junit.Ignore
44 import org.junit.Test
45 import org.junit.runner.RunWith
46 import org.junit.runners.MethodSorters
47 import org.junit.runners.Parameterized
48 
49 /**
50  * Test cold launching an app from a notification.
51  *
52  * To run this test: `atest FlickerTestsNotification:OpenAppFromNotificationWarmTest`
53  */
54 @RunWith(Parameterized::class)
55 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
56 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
57 open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
58     OpenAppTransition(flicker) {
59     override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
60 
61     /** {@inheritDoc} */
62     override val transition: FlickerBuilder.() -> Unit
<lambda>null63         get() = {
64             setup {
65                 device.wakeUpAndGoToHomeScreen()
66                 this.setRotation(flicker.scenario.startRotation)
67                 launchAppAndPostNotification()
68                 goHome()
69             }
70 
71             transitions { openAppFromNotification() }
72 
73             teardown { testApp.exit(wmHelper) }
74         }
75 
launchAppAndPostNotificationnull76     protected fun FlickerTestData.launchAppAndPostNotification() {
77         testApp.launchViaIntent(wmHelper)
78         wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
79         testApp.postNotification(wmHelper)
80     }
81 
FlickerTestDatanull82     protected fun FlickerTestData.goHome() {
83         device.pressHome()
84         wmHelper
85             .StateSyncBuilder()
86             .withHomeActivityVisible()
87             .withWindowSurfaceDisappeared(ComponentNameMatcher.NOTIFICATION_SHADE)
88             .waitForAndVerify()
89     }
90 
openAppFromNotificationnull91     protected fun FlickerTestData.openAppFromNotification() {
92         doOpenAppAndWait()
93     }
94 
FlickerTestDatanull95     protected fun FlickerTestData.openAppFromLockNotification() {
96         val wm: WindowManager =
97             instrumentation.context.getSystemService(WindowManager::class.java)
98                 ?: error("Unable to connect to WindowManager service")
99         val metricInsets = wm.currentWindowMetrics.windowInsets
100         val insets =
101             metricInsets.getInsetsIgnoringVisibility(
102                 WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
103             )
104 
105         doOpenAppAndWait()
106     }
107 
FlickerTestDatanull108     protected fun FlickerTestData.doOpenAppAndWait() {
109         val shade = Root.get().openNotificationShade()
110 
111         // Launch the activity by clicking the notification
112         // Post notification and ensure that it's collapsed
113         val notification =
114             shade.notificationStack.findNotification(
115                 NotificationIdentity(
116                     type = NotificationIdentity.Type.BY_TEXT,
117                     text = "Flicker Test Notification",
118                 )
119             )
120 
121         notification.clickToApp()
122         // Wait for the app to launch
123         wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
124     }
125 
appWindowBecomesVisiblenull126     @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
127 
128     @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
129 
130     @Presubmit
131     @Test
132     open fun notificationAppWindowVisibleAtEnd() {
133         flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
134     }
135 
136     @Presubmit
137     @Test
notificationAppWindowOnTopAtEndnull138     open fun notificationAppWindowOnTopAtEnd() {
139         flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
140     }
141 
142     @Presubmit
143     @Test
notificationAppLayerVisibleAtEndnull144     open fun notificationAppLayerVisibleAtEnd() {
145         flicker.assertLayersEnd { this.isVisible(testApp) }
146     }
147 
148     /**
149      * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the end of the
150      * transition
151      *
152      * Note: Large screen only
153      */
154     @Presubmit
155     @Test
taskBarWindowIsVisibleAtEndnull156     open fun taskBarWindowIsVisibleAtEnd() {
157         Assume.assumeTrue(usesTaskbar)
158         flicker.taskBarWindowIsVisibleAtEnd()
159     }
160 
161     /**
162      * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the transition
163      *
164      * Note: Large screen only
165      */
166     @Presubmit
167     @Test
taskBarLayerIsVisibleAtEndnull168     open fun taskBarLayerIsVisibleAtEnd() {
169         Assume.assumeTrue(usesTaskbar)
170         flicker.taskBarLayerIsVisibleAtEnd()
171     }
172 
173     /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
174     @Presubmit
175     @Test
navBarLayerPositionAtEndnull176     open fun navBarLayerPositionAtEnd() {
177         Assume.assumeFalse(usesTaskbar)
178         flicker.navBarLayerPositionAtEnd()
179     }
180 
181     /** {@inheritDoc} */
182     @Presubmit
183     @Test
navBarLayerIsVisibleAtEndnull184     open fun navBarLayerIsVisibleAtEnd() {
185         Assume.assumeFalse(usesTaskbar)
186         flicker.navBarLayerIsVisibleAtEnd()
187     }
188 
189     @Presubmit
190     @Test
navBarWindowIsVisibleAtEndnull191     open fun navBarWindowIsVisibleAtEnd() {
192         Assume.assumeFalse(usesTaskbar)
193         flicker.navBarWindowIsVisibleAtEnd()
194     }
195 
196     /** {@inheritDoc} */
197     @Test
198     @Ignore("Display is off at the start")
taskBarLayerIsVisibleAtStartAndEndnull199     override fun taskBarLayerIsVisibleAtStartAndEnd() {}
200 
201     /** {@inheritDoc} */
202     @Test
203     @Postsubmit
taskBarWindowIsAlwaysVisiblenull204     override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
205 
206     companion object {
207         /**
208          * Creates the test configurations.
209          *
210          * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
211          * navigation modes.
212          */
213         @Parameterized.Parameters(name = "{0}")
214         @JvmStatic
215         fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
216 
217         /** Ensures that posted notifications will alert and HUN even just after boot. */
218         @ClassRule
219         @JvmField
220         val disablenotificationCooldown = DisableNotificationCooldownSettingRule()
221     }
222 }
223