1 /*
2  * Copyright (C) 2020 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.ime
18 
19 import android.platform.test.annotations.Presubmit
20 import android.tools.common.Rotation
21 import android.tools.common.traces.component.ComponentNameMatcher
22 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
23 import android.tools.device.flicker.legacy.FlickerBuilder
24 import android.tools.device.flicker.legacy.LegacyFlickerTest
25 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
26 import android.tools.device.helpers.reopenAppFromOverview
27 import androidx.test.filters.RequiresDevice
28 import com.android.server.wm.flicker.BaseTest
29 import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
30 import com.android.server.wm.flicker.helpers.setRotation
31 import org.junit.FixMethodOrder
32 import org.junit.Test
33 import org.junit.runner.RunWith
34 import org.junit.runners.MethodSorters
35 import org.junit.runners.Parameterized
36 
37 /**
38  * Test IME window opening transitions. To run this test: `atest FlickerTests:ReOpenImeWindowTest`
39  */
40 @RequiresDevice
41 @RunWith(Parameterized::class)
42 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
43 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
44 open class ShowImeOnAppStartWhenLaunchingAppFromOverviewTest(flicker: LegacyFlickerTest) :
45     BaseTest(flicker) {
46     private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
47 
48     /** {@inheritDoc} */
49     override val transition: FlickerBuilder.() -> Unit = {
50         setup {
51             tapl.workspace.switchToOverview().dismissAllTasks()
52             testApp.launchViaIntent(wmHelper)
53             testApp.openIME(wmHelper)
54             this.setRotation(flicker.scenario.startRotation)
55             device.pressRecentApps()
56             wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
57         }
58         transitions {
59             device.reopenAppFromOverview(wmHelper)
60             wmHelper.StateSyncBuilder().withFullScreenApp(testApp).withImeShown().waitForAndVerify()
61         }
62         teardown { testApp.exit(wmHelper) }
63     }
64 
65     /** {@inheritDoc} */
66     @Presubmit
67     @Test
68     override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
69         // depends on how much of the animation transactions are sent to SF at once
70         // sometimes this layer appears for 2-3 frames, sometimes for only 1
71         val recentTaskComponent = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
72         flicker.assertLayers {
73             this.visibleLayersShownMoreThanOneConsecutiveEntry(
74                 listOf(
75                     ComponentNameMatcher.SPLASH_SCREEN,
76                     ComponentNameMatcher.SNAPSHOT,
77                     recentTaskComponent
78                 )
79             )
80         }
81     }
82 
83     /** {@inheritDoc} */
84     @Presubmit
85     @Test
86     override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
87         val component = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
88         flicker.assertWm {
89             this.visibleWindowsShownMoreThanOneConsecutiveEntry(
90                 ignoreWindows =
91                     listOf(
92                         ComponentNameMatcher.SPLASH_SCREEN,
93                         ComponentNameMatcher.SNAPSHOT,
94                         component
95                     )
96             )
97         }
98     }
99 
100     @Presubmit
101     @Test
102     fun launcherWindowBecomesInvisible() {
103         flicker.assertWm {
104             this.isAppWindowVisible(ComponentNameMatcher.LAUNCHER)
105                 .then()
106                 .isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
107         }
108     }
109 
110     @Presubmit @Test fun imeWindowIsAlwaysVisible() = flicker.imeWindowIsAlwaysVisible()
111 
112     @Presubmit
113     @Test
114     fun imeAppWindowIsAlwaysVisible() {
115         // the app starts visible in live tile, and stays visible for the duration of entering
116         // and exiting overview. Since we log 1x per frame, sometimes the activity visibility
117         // and the app visibility are updated together, sometimes not, thus ignore activity
118         // check at the start
119         flicker.assertWm { this.isAppWindowVisible(testApp) }
120     }
121 
122     @Presubmit
123     @Test
124     fun imeLayerBecomesVisible() {
125         flicker.assertLayers { this.isVisible(ComponentNameMatcher.IME) }
126     }
127 
128     @Presubmit
129     @Test
130     fun appLayerReplacesLauncher() {
131         flicker.assertLayers {
132             this.isVisible(ComponentNameMatcher.LAUNCHER)
133                 .then()
134                 .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
135                 .then()
136                 .isVisible(testApp)
137         }
138     }
139 
140     companion object {
141         @Parameterized.Parameters(name = "{0}")
142         @JvmStatic
143         fun getParams() =
144             LegacyFlickerTestFactory.nonRotationTests(
145                 supportedRotations = listOf(Rotation.ROTATION_0)
146             )
147     }
148 }
149