1 /* 2 * Copyright (C) 2022 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.traces.ConditionsFactory 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.traces.parsers.WindowManagerStateHelper 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.navBarLayerIsVisibleAtStartAndEnd 31 import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd 32 import org.junit.Assume 33 import org.junit.FixMethodOrder 34 import org.junit.Ignore 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 import org.junit.runners.MethodSorters 38 import org.junit.runners.Parameterized 39 40 /** 41 * Test IME window layer will be associated with the app task when going to the overview screen. To 42 * run this test: `atest FlickerTests:OpenImeWindowToOverViewTest` 43 */ 44 @RequiresDevice 45 @RunWith(Parameterized::class) 46 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) 47 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 48 open class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(flicker) { 49 private val imeTestApp = 50 ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation) 51 52 /** {@inheritDoc} */ 53 override val transition: FlickerBuilder.() -> Unit = { 54 setup { imeTestApp.launchViaIntent(wmHelper) } 55 transitions { 56 device.pressRecentApps() 57 val builder = wmHelper.StateSyncBuilder().withRecentsActivityVisible() 58 waitNavStatusBarVisibility(builder) 59 builder.waitForAndVerify() 60 } 61 teardown { 62 device.pressHome() 63 wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify() 64 imeTestApp.exit(wmHelper) 65 } 66 } 67 68 /** 69 * The bars (including [ComponentNameMatcher.STATUS_BAR] and [ComponentNameMatcher.NAV_BAR]) are 70 * expected to be hidden while entering overview in landscape if launcher is set to portrait 71 * only. Because "showing portrait overview (launcher) in landscape display" is an intermediate 72 * state depending on the touch-up to decide the intention of gesture, the display may keep in 73 * landscape if return to app, or change to portrait if the gesture is to swipe-to-home. 74 * 75 * So instead of showing landscape bars with portrait launcher at the same time (especially 76 * return-to-home that launcher workspace becomes visible), hide the bars until leave overview 77 * to have cleaner appearance. 78 * 79 * b/227189877 80 */ 81 private fun waitNavStatusBarVisibility(stateSync: WindowManagerStateHelper.StateSyncBuilder) { 82 when { 83 flicker.scenario.isLandscapeOrSeascapeAtStart && !flicker.scenario.isTablet -> 84 stateSync.add(ConditionsFactory.isStatusBarVisible().negate()) 85 else -> stateSync.withNavOrTaskBarVisible().withStatusBarVisible() 86 } 87 } 88 89 @Presubmit 90 @Test 91 fun imeWindowIsAlwaysVisible() { 92 flicker.imeWindowIsAlwaysVisible() 93 } 94 95 @Presubmit 96 @Test 97 fun navBarLayerIsVisibleAtStartAndEnd3Button() { 98 Assume.assumeFalse(flicker.scenario.isTablet) 99 Assume.assumeFalse(flicker.scenario.isGesturalNavigation) 100 flicker.navBarLayerIsVisibleAtStartAndEnd() 101 } 102 103 /** 104 * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions 105 * this is fixed and the nav bar shows as invisible 106 */ 107 @Presubmit 108 @Test 109 fun navBarLayerIsInvisibleInLandscapeGestural() { 110 Assume.assumeFalse(flicker.scenario.isTablet) 111 Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) 112 Assume.assumeTrue(flicker.scenario.isGesturalNavigation) 113 flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.NAV_BAR) } 114 flicker.assertLayersEnd { this.isInvisible(ComponentNameMatcher.NAV_BAR) } 115 } 116 117 /** 118 * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions 119 * this is fixed and the nav bar shows as invisible 120 */ 121 @Presubmit 122 @Test 123 fun statusBarLayerIsInvisibleInLandscapePhone() { 124 Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) 125 Assume.assumeTrue(flicker.scenario.isGesturalNavigation) 126 Assume.assumeFalse(flicker.scenario.isTablet) 127 flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) } 128 flicker.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) } 129 } 130 131 /** 132 * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions 133 * this is fixed and the nav bar shows as invisible 134 */ 135 @Presubmit 136 @Test 137 fun statusBarLayerIsInvisibleInLandscapeTablet() { 138 Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) 139 Assume.assumeTrue(flicker.scenario.isGesturalNavigation) 140 Assume.assumeTrue(flicker.scenario.isTablet) 141 flicker.statusBarLayerIsVisibleAtStartAndEnd() 142 } 143 144 /** {@inheritDoc} */ 145 @Test 146 @Ignore("Visibility changes depending on orientation and navigation mode") 147 override fun navBarLayerIsVisibleAtStartAndEnd() {} 148 149 /** {@inheritDoc} */ 150 @Test 151 @Ignore("Visibility changes depending on orientation and navigation mode") 152 override fun navBarLayerPositionAtStartAndEnd() {} 153 154 /** {@inheritDoc} */ 155 @Test 156 @Ignore("Visibility changes depending on orientation and navigation mode") 157 override fun statusBarLayerPositionAtStartAndEnd() {} 158 159 /** {@inheritDoc} */ 160 @Test 161 @Ignore("Visibility changes depending on orientation and navigation mode") 162 override fun statusBarLayerIsVisibleAtStartAndEnd() {} 163 164 @Presubmit 165 @Test 166 override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() 167 168 @Presubmit 169 @Test 170 fun statusBarLayerIsVisibleInPortrait() { 171 Assume.assumeFalse(flicker.scenario.isLandscapeOrSeascapeAtStart) 172 flicker.statusBarLayerIsVisibleAtStartAndEnd() 173 } 174 175 @Presubmit 176 @Test 177 fun statusBarLayerIsInvisibleInLandscape() { 178 Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) 179 Assume.assumeFalse(flicker.scenario.isTablet) 180 flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) } 181 flicker.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) } 182 } 183 184 @Presubmit 185 @Test 186 fun imeLayerIsVisibleAndAssociatedWithAppWidow() { 187 flicker.assertLayersStart { 188 isVisible(ComponentNameMatcher.IME) 189 .visibleRegion(ComponentNameMatcher.IME) 190 .coversAtMost(isVisible(imeTestApp).visibleRegion(imeTestApp).region) 191 } 192 flicker.assertLayers { 193 this.invoke("imeLayerIsVisibleAndAlignAppWidow") { 194 val imeVisibleRegion = it.visibleRegion(ComponentNameMatcher.IME) 195 val appVisibleRegion = it.visibleRegion(imeTestApp) 196 if (imeVisibleRegion.region.isNotEmpty) { 197 it.isVisible(ComponentNameMatcher.IME) 198 imeVisibleRegion.coversAtMost(appVisibleRegion.region) 199 } 200 } 201 } 202 } 203 204 companion object { 205 /** 206 * Creates the test configurations. 207 * 208 * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and 209 * navigation modes. 210 */ 211 @Parameterized.Parameters(name = "{0}") 212 @JvmStatic 213 fun getParams() = LegacyFlickerTestFactory.nonRotationTests() 214 } 215 } 216