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.test.annotations.Postsubmit
20 import android.platform.test.annotations.Presubmit
21 import android.platform.test.rule.DisableNotificationCooldownSettingRule
22 import android.tools.flicker.junit.FlickerParametersRunnerFactory
23 import android.tools.flicker.legacy.FlickerBuilder
24 import android.tools.flicker.legacy.FlickerTestData
25 import android.tools.flicker.legacy.LegacyFlickerTest
26 import android.tools.flicker.legacy.LegacyFlickerTestFactory
27 import android.tools.helpers.wakeUpAndGoToHomeScreen
28 import android.tools.traces.component.ComponentNameMatcher
29 import android.view.WindowInsets
30 import android.view.WindowManager
31 import androidx.test.uiautomator.By
32 import androidx.test.uiautomator.Until
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     }
openAppFromNotificationnull90     protected fun FlickerTestData.openAppFromNotification() {
91         doOpenAppAndWait(startY = 10, endY = 3 * device.displayHeight / 4, steps = 25)
92     }
93 
FlickerTestDatanull94     protected fun FlickerTestData.openAppFromLockNotification() {
95         val wm: WindowManager =
96             instrumentation.context.getSystemService(WindowManager::class.java)
97                 ?: error("Unable to connect to WindowManager service")
98         val metricInsets = wm.currentWindowMetrics.windowInsets
99         val insets =
100             metricInsets.getInsetsIgnoringVisibility(
101                 WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
102             )
103 
104         doOpenAppAndWait(startY = insets.top + 100, endY = device.displayHeight / 2, steps = 4)
105     }
106 
FlickerTestDatanull107     protected fun FlickerTestData.doOpenAppAndWait(startY: Int, endY: Int, steps: Int) {
108         // Swipe down to show the notification shade
109         val x = device.displayWidth / 2
110         device.swipe(x, startY, x, endY, steps)
111         device.waitForIdle(2000)
112         instrumentation.uiAutomation.syncInputTransactions()
113 
114         // Launch the activity by clicking the notification
115         val notification =
116             device.wait(Until.findObject(By.text("Flicker Test Notification")), 2000L)
117         notification?.click() ?: error("Notification not found")
118         instrumentation.uiAutomation.syncInputTransactions()
119 
120         // Wait for the app to launch
121         wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
122     }
appWindowBecomesVisiblenull123     @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
124 
125     @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
126 
127     @Presubmit
128     @Test
129     open fun notificationAppWindowVisibleAtEnd() {
130         flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
131     }
132 
133     @Presubmit
134     @Test
notificationAppWindowOnTopAtEndnull135     open fun notificationAppWindowOnTopAtEnd() {
136         flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
137     }
138 
139     @Presubmit
140     @Test
notificationAppLayerVisibleAtEndnull141     open fun notificationAppLayerVisibleAtEnd() {
142         flicker.assertLayersEnd { this.isVisible(testApp) }
143     }
144 
145     /**
146      * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the end of the
147      * transition
148      *
149      * Note: Large screen only
150      */
151     @Presubmit
152     @Test
taskBarWindowIsVisibleAtEndnull153     open fun taskBarWindowIsVisibleAtEnd() {
154         Assume.assumeTrue(flicker.scenario.isTablet)
155         flicker.taskBarWindowIsVisibleAtEnd()
156     }
157 
158     /**
159      * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the transition
160      *
161      * Note: Large screen only
162      */
163     @Presubmit
164     @Test
taskBarLayerIsVisibleAtEndnull165     open fun taskBarLayerIsVisibleAtEnd() {
166         Assume.assumeTrue(flicker.scenario.isTablet)
167         flicker.taskBarLayerIsVisibleAtEnd()
168     }
169 
170     /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
171     @Presubmit
172     @Test
navBarLayerPositionAtEndnull173     open fun navBarLayerPositionAtEnd() {
174         Assume.assumeFalse(flicker.scenario.isTablet)
175         flicker.navBarLayerPositionAtEnd()
176     }
177 
178     /** {@inheritDoc} */
179     @Presubmit
180     @Test
navBarLayerIsVisibleAtEndnull181     open fun navBarLayerIsVisibleAtEnd() {
182         Assume.assumeFalse(flicker.scenario.isTablet)
183         flicker.navBarLayerIsVisibleAtEnd()
184     }
185 
186     @Presubmit
187     @Test
navBarWindowIsVisibleAtEndnull188     open fun navBarWindowIsVisibleAtEnd() {
189         Assume.assumeFalse(flicker.scenario.isTablet)
190         flicker.navBarWindowIsVisibleAtEnd()
191     }
192 
193     /** {@inheritDoc} */
194     @Test
195     @Ignore("Display is off at the start")
taskBarLayerIsVisibleAtStartAndEndnull196     override fun taskBarLayerIsVisibleAtStartAndEnd() {}
197 
198     /** {@inheritDoc} */
199     @Test
200     @Postsubmit
taskBarWindowIsAlwaysVisiblenull201     override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
202 
203     companion object {
204         /**
205          * Creates the test configurations.
206          *
207          * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
208          * navigation modes.
209          */
210         @Parameterized.Parameters(name = "{0}")
211         @JvmStatic
212         fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
213 
214         /** Ensures that posted notifications will alert and HUN even just after boot. */
215         @ClassRule
216         @JvmField
217         val disablenotificationCooldown = DisableNotificationCooldownSettingRule()
218     }
219 }
220