Merge "Fix typo" into udc-qpr-dev
diff --git a/libraries/flicker/src/android/tools/device/flicker/datastore/CachedAssertionRunner.kt b/libraries/flicker/src/android/tools/device/flicker/datastore/CachedAssertionRunner.kt
index 7e6d23d..3c3ff50 100644
--- a/libraries/flicker/src/android/tools/device/flicker/datastore/CachedAssertionRunner.kt
+++ b/libraries/flicker/src/android/tools/device/flicker/datastore/CachedAssertionRunner.kt
@@ -17,6 +17,7 @@
 package android.tools.device.flicker.datastore
 
 import android.tools.common.Scenario
+import android.tools.common.io.Reader
 import android.tools.common.io.RunStatus
 import android.tools.device.flicker.assertions.BaseAssertionRunner
 import android.tools.device.traces.TRACE_CONFIG_REQUIRE_CHANGES
@@ -29,7 +30,7 @@
  */
 class CachedAssertionRunner(
     private val scenario: Scenario,
-    resultReader: CachedResultReader = CachedResultReader(scenario, TRACE_CONFIG_REQUIRE_CHANGES)
+    resultReader: Reader = CachedResultReader(scenario, TRACE_CONFIG_REQUIRE_CHANGES)
 ) : BaseAssertionRunner(resultReader) {
     override fun doUpdateStatus(newStatus: RunStatus) {
         val result = DataStore.getResult(scenario)
diff --git a/libraries/flicker/src/android/tools/device/flicker/legacy/LegacyFlickerTest.kt b/libraries/flicker/src/android/tools/device/flicker/legacy/LegacyFlickerTest.kt
index 2696408..0616e4b 100644
--- a/libraries/flicker/src/android/tools/device/flicker/legacy/LegacyFlickerTest.kt
+++ b/libraries/flicker/src/android/tools/device/flicker/legacy/LegacyFlickerTest.kt
@@ -31,7 +31,7 @@
 /** Specification of a flicker test for JUnit ParameterizedRunner class */
 data class LegacyFlickerTest(
     private val scenarioBuilder: ScenarioBuilder = ScenarioBuilder(),
-    private val resultReaderProvider: (Scenario) -> CachedResultReader = {
+    private val resultReaderProvider: (Scenario) -> Reader = {
         CachedResultReader(it, TRACE_CONFIG_REQUIRE_CHANGES)
     },
     private val subjectsParserProvider: (Reader) -> SubjectsParser = { SubjectsParser(it) },
diff --git a/libraries/flicker/src/android/tools/device/traces/parsers/WindowManagerStateHelper.kt b/libraries/flicker/src/android/tools/device/traces/parsers/WindowManagerStateHelper.kt
index de4fea8..6fdb369 100644
--- a/libraries/flicker/src/android/tools/device/traces/parsers/WindowManagerStateHelper.kt
+++ b/libraries/flicker/src/android/tools/device/traces/parsers/WindowManagerStateHelper.kt
@@ -312,6 +312,24 @@
                 .add(ConditionsFactory.isLayerVisible(componentMatcher))
 
         /**
+         * Wait until least one layer matching [componentMatcher] has [expectedRegion]
+         *
+         * @param componentMatcher Components to search
+         * @param expectedRegion of the target surface
+         */
+        fun withSurfaceVisibleRegion(componentMatcher: IComponentMatcher, expectedRegion: Region) =
+            add(
+                Condition("surfaceRegion") {
+                    val layer =
+                        it.layerState.visibleLayers.firstOrNull { layer ->
+                            componentMatcher.layerMatchesAnyOf(layer)
+                        }
+
+                    layer?.visibleRegion == expectedRegion
+                }
+            )
+
+        /**
          * Waits until the IME window and layer are visible
          *
          * @param displayId of the target display
diff --git a/libraries/flicker/test/assets/testdata/layers_trace_snapshotStartingWindowLayerCoversExactlyApp.winscope b/libraries/flicker/test/assets/testdata/layers_trace_snapshotStartingWindowLayerCoversExactlyApp.winscope
new file mode 100644
index 0000000..d9c577d
--- /dev/null
+++ b/libraries/flicker/test/assets/testdata/layers_trace_snapshotStartingWindowLayerCoversExactlyApp.winscope
Binary files differ
diff --git a/libraries/flicker/test/src/android/tools/Utils.kt b/libraries/flicker/test/src/android/tools/Utils.kt
index dfe2611..0096e12 100644
--- a/libraries/flicker/test/src/android/tools/Utils.kt
+++ b/libraries/flicker/test/src/android/tools/Utils.kt
@@ -21,6 +21,7 @@
 import android.tools.common.Scenario
 import android.tools.common.ScenarioBuilder
 import android.tools.common.ScenarioImpl
+import android.tools.common.Timestamp
 import android.tools.common.Timestamps
 import android.tools.common.io.Reader
 import android.tools.common.io.ResultArtifactDescriptor
@@ -115,6 +116,8 @@
     relativePath: String,
     ignoreOrphanLayers: Boolean = true,
     legacyTrace: Boolean = false,
+    from: Timestamp = Timestamps.min(),
+    to: Timestamp = Timestamps.max()
 ): Reader {
     return ParsedTracesReader(
         artifact = InMemoryArtifact(relativePath),
@@ -126,7 +129,7 @@
                 ) {
                     ignoreOrphanLayers
                 }
-                .parse(readAsset(relativePath))
+                .parse(readAsset(relativePath), from, to)
     )
 }
 
diff --git a/libraries/flicker/test/src/android/tools/common/flicker/subject/surfaceflinger/LayersTraceSubjectTest.kt b/libraries/flicker/test/src/android/tools/common/flicker/subject/surfaceflinger/LayersTraceSubjectTest.kt
index 5a2b9a0..c2d525f 100644
--- a/libraries/flicker/test/src/android/tools/common/flicker/subject/surfaceflinger/LayersTraceSubjectTest.kt
+++ b/libraries/flicker/test/src/android/tools/common/flicker/subject/surfaceflinger/LayersTraceSubjectTest.kt
@@ -21,10 +21,16 @@
 import android.tools.assertThatErrorContainsDebugInfo
 import android.tools.assertThrows
 import android.tools.common.Cache
+import android.tools.common.ScenarioBuilder
+import android.tools.common.Timestamps
 import android.tools.common.datatypes.Region
 import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.region.RegionSubject
 import android.tools.common.io.Reader
 import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.datastore.DataStore
+import android.tools.device.flicker.legacy.LegacyFlickerTest
+import android.tools.device.traces.io.IResultData
 import android.tools.getLayerTraceReaderFromAsset
 import android.tools.rules.CleanFlickerEnvironmentRule
 import androidx.test.filters.FlakyTest
@@ -34,6 +40,7 @@
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runners.MethodSorters
+import org.mockito.Mockito
 
 /**
  * Contains [LayersTraceSubject] tests. To run this test: `atest
@@ -342,7 +349,46 @@
         }
     }
 
+    @Test
+    fun snapshotStartingWindowLayerCoversExactlyApp() {
+        val reader =
+            getLayerTraceReaderFromAsset(
+                "layers_trace_snapshotStartingWindowLayerCoversExactlyApp.winscope",
+                from = Timestamps.from(systemUptimeNanos = 1688243428961872440),
+                to = Timestamps.from(systemUptimeNanos = 1688243432147782644)
+            )
+        val component =
+            ComponentNameMatcher(FLICKER_APP_PACKAGE, "$FLICKER_APP_PACKAGE.ImeActivity")
+        val builder = ScenarioBuilder()
+        val flicker = LegacyFlickerTest(builder, { _ -> reader })
+        val scenario = flicker.initialize("test")
+        val result = Mockito.mock(IResultData::class.java)
+        DataStore.addResult(scenario, result)
+        flicker.assertLayers {
+            invoke("snapshotStartingWindowLayerCoversExactlyOnApp") {
+                val snapshotLayers =
+                    it.subjects.filter { subject ->
+                        ComponentNameMatcher.SNAPSHOT.layerMatchesAnyOf(subject.layer) &&
+                            subject.isVisible
+                    }
+                val visibleAreas =
+                    snapshotLayers
+                        .mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
+                        .toTypedArray()
+                val snapshotRegion = RegionSubject(visibleAreas, timestamp)
+                // Verify the size of snapshotRegion covers appVisibleRegion exactly in animation.
+                if (snapshotRegion.region.isNotEmpty) {
+                    val appVisibleRegion = it.visibleRegion(component)
+                    snapshotRegion.coversExactly(appVisibleRegion.region)
+                }
+            }
+        }
+    }
+
     companion object {
+        private const val LABEL = "ImeActivity"
+        private const val FLICKER_APP_PACKAGE = "com.android.server.wm.flicker.testapp"
+
         private val DISPLAY_REGION = Region.from(0, 0, 1440, 2880)
         private val DISPLAY_REGION_ROTATED = Region.from(0, 0, 2160, 1080)
 
diff --git a/libraries/screenshot/src/main/java/platform/test/screenshot/DeviceEmulationRule.kt b/libraries/screenshot/src/main/java/platform/test/screenshot/DeviceEmulationRule.kt
index b49f1aa..fcaecca 100644
--- a/libraries/screenshot/src/main/java/platform/test/screenshot/DeviceEmulationRule.kt
+++ b/libraries/screenshot/src/main/java/platform/test/screenshot/DeviceEmulationRule.kt
@@ -73,7 +73,9 @@
             val runtimeEnvironment = Class.forName("org.robolectric.RuntimeEnvironment")
             val setQualifiers =
                 runtimeEnvironment.getDeclaredMethod("setQualifiers", String::class.java)
-            val qualifier = "w${width}dp-h${height}dp-${density}dpi"
+            val scaledWidth = width * 160 / density
+            val scaledHeight = height * 160 / density
+            val qualifier = "w${scaledWidth}dp-h${scaledHeight}dp-${density}dpi"
             setQualifiers.invoke(null, qualifier)
         } else {
             // Make sure that we are in natural orientation (rotation 0) before we set the screen size