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.Postsubmit 20 import android.platform.test.annotations.Presubmit 21 import android.tools.common.Rotation 22 import android.tools.common.Timestamp 23 import android.tools.common.flicker.subject.exceptions.ExceptionMessageBuilder 24 import android.tools.common.flicker.subject.exceptions.InvalidPropertyException 25 import android.tools.common.traces.component.ComponentNameMatcher 26 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory 27 import android.tools.device.flicker.legacy.FlickerBuilder 28 import android.tools.device.flicker.legacy.LegacyFlickerTest 29 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory 30 import androidx.test.filters.RequiresDevice 31 import com.android.server.wm.flicker.BaseTest 32 import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper 33 import com.android.server.wm.flicker.helpers.setRotation 34 import com.android.server.wm.flicker.snapshotStartingWindowLayerCoversExactlyOnApp 35 import org.junit.FixMethodOrder 36 import org.junit.Test 37 import org.junit.runner.RunWith 38 import org.junit.runners.MethodSorters 39 import org.junit.runners.Parameterized 40 41 /** 42 * Test IME window layer will become visible when switching from the fixed orientation activity 43 * (e.g. Launcher activity). To run this test: `atest 44 * FlickerTests:ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest` 45 */ 46 @RequiresDevice 47 @RunWith(Parameterized::class) 48 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) 49 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 50 open class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker: LegacyFlickerTest) : 51 BaseTest(flicker) { 52 private val imeTestApp = 53 ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation) 54 55 /** {@inheritDoc} */ 56 override val transition: FlickerBuilder.() -> Unit = { 57 setup { 58 tapl.setExpectedRotationCheckEnabled(false) 59 60 // Launch the activity with expecting IME will be shown. 61 imeTestApp.launchViaIntent(wmHelper) 62 63 // Swiping out the IME activity to home. 64 tapl.goHome() 65 wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify() 66 } 67 transitions { 68 // Bring the existing IME activity to the front in landscape mode device rotation. 69 setRotation(Rotation.ROTATION_90) 70 imeTestApp.launchViaIntent(wmHelper) 71 } 72 teardown { imeTestApp.exit(wmHelper) } 73 } 74 75 @Presubmit @Test fun imeWindowBecomesVisible() = flicker.imeWindowBecomesVisible() 76 77 @Presubmit @Test fun imeLayerBecomesVisible() = flicker.imeLayerBecomesVisible() 78 79 @Presubmit 80 @Test 81 fun snapshotStartingWindowLayerCoversExactlyOnApp() { 82 flicker.snapshotStartingWindowLayerCoversExactlyOnApp(imeTestApp) 83 } 84 85 @Postsubmit 86 @Test 87 fun imeLayerAlphaOneAfterSnapshotStartingWindowRemoval() { 88 // Check if the snapshot appeared during the trace 89 var imeSnapshotRemovedTimestamp: Timestamp? = null 90 91 val layerTrace = flicker.reader.readLayersTrace() 92 val layerTraceEntries = layerTrace?.entries?.toList() ?: emptyList() 93 94 layerTraceEntries.zipWithNext { prev, next -> 95 val prevSnapshotLayerVisible = 96 ComponentNameMatcher.SNAPSHOT.layerMatchesAnyOf(prev.visibleLayers) 97 val nextSnapshotLayerVisible = 98 ComponentNameMatcher.SNAPSHOT.layerMatchesAnyOf(next.visibleLayers) 99 100 if ( 101 imeSnapshotRemovedTimestamp == null && 102 (prevSnapshotLayerVisible && !nextSnapshotLayerVisible) 103 ) { 104 imeSnapshotRemovedTimestamp = next.timestamp 105 } 106 } 107 108 // if so, make an assertion 109 imeSnapshotRemovedTimestamp?.let { timestamp -> 110 val stateAfterSnapshot = 111 layerTrace?.getEntryAt(timestamp) ?: error("State not found for $timestamp") 112 113 val imeLayers = 114 ComponentNameMatcher.IME.filterLayers(stateAfterSnapshot.visibleLayers.toList()) 115 116 require(imeLayers.isNotEmpty()) { "IME layer not found" } 117 if (imeLayers.any { it.color.a != 1.0f }) { 118 val errorMsgBuilder = 119 ExceptionMessageBuilder() 120 .setTimestamp(timestamp) 121 .forInvalidProperty("IME layer alpha") 122 .setExpected("is 1.0") 123 .setActual("not 1.0") 124 .addExtraDescription("Filter", ComponentNameMatcher.IME.toLayerIdentifier()) 125 throw InvalidPropertyException(errorMsgBuilder) 126 } 127 } 128 } 129 130 companion object { 131 /** 132 * Creates the test configurations. 133 * 134 * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and 135 * navigation modes. 136 */ 137 @Parameterized.Parameters(name = "{0}") 138 @JvmStatic 139 fun getParams() = 140 LegacyFlickerTestFactory.nonRotationTests( 141 supportedRotations = listOf(Rotation.ROTATION_90) 142 ) 143 } 144 } 145