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