Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/SplitScreenUtils.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import com.android.server.wm.flicker.testapp.ActivityOptions import com.android.server.wm.flicker.testapp.ActivityOptions.SplitScreen.Primary import org.junit.Assert.assertNotNull internal object SplitScreenUtils { object SplitScreenUtils { private const val TIMEOUT_MS = 3_000L private const val DRAG_DURATION_MS = 1_000L private const val NOTIFICATION_SCROLLER = "notification_stack_scroller" Loading tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker.activityembedding import android.platform.test.annotations.Presubmit import android.tools.common.datatypes.Rect import android.tools.common.traces.component.ComponentNameMatcher import android.tools.common.traces.component.ComponentNameMatcher.Companion.TRANSITION_SNAPSHOT import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.LegacyFlickerTest import android.tools.device.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test launching a secondary Activity into Picture-In-Picture mode. * * Setup: Start from a split A|B. * Transition: B enters PIP, observe the window shrink to the bottom right corner on screen. * * To run this test: `atest FlickerTests:SecondaryActivityEnterPipTest` * */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class SecondaryActivityEnterPipTest (flicker: LegacyFlickerTest) : ActivityEmbeddingTestBase(flicker) { override val transition: FlickerBuilder.() -> Unit = { setup { tapl.setExpectedRotationCheckEnabled(false) testApp.launchViaIntent(wmHelper) testApp.launchSecondaryActivity(wmHelper) startDisplayBounds = wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Can't get display bounds") } transitions { testApp.secondaryActivityEnterPip(wmHelper) } teardown { tapl.goHome() testApp.exit(wmHelper) } } /** * Main and secondary activity start from a split each taking half of the screen. */ @Presubmit @Test fun layersStartFromEqualSplit() { flicker.assertLayersStart { val leftLayerRegion = visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) val rightLayerRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) // Compare dimensions of two splits, given we're using default split attributes, // both activities take up the same visible size on the display. check { "height" } .that(leftLayerRegion.region.height).isEqual(rightLayerRegion.region.height) check { "width" } .that(leftLayerRegion.region.width).isEqual(rightLayerRegion.region.width) leftLayerRegion.notOverlaps(rightLayerRegion.region) leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds) } flicker.assertLayersEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Main Activity is visible throughout the transition and becomes fullscreen. */ @Presubmit @Test fun mainActivityWindowBecomesFullScreen() { flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) } flicker.assertWmEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Main Activity is visible throughout the transition and becomes fullscreen. */ @Presubmit @Test fun mainActivityLayerBecomesFullScreen() { flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .then() .isVisible(TRANSITION_SNAPSHOT) .isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .then() .isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) } flicker.assertLayersEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Secondary Activity is visible throughout the transition and shrinks to the bottom right * corner. */ @Presubmit @Test fun secondaryWindowShrinks() { flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) } flicker.assertWmEnd { val pipWindowRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) check{"height"} .that(pipWindowRegion.region.height) .isLower(startDisplayBounds.height / 2) check{"width"} .that(pipWindowRegion.region.width).isLower(startDisplayBounds.width) } } /** * During the transition Secondary Activity shrinks to the bottom right corner. */ @Presubmit @Test fun secondaryLayerShrinks() { flicker.assertLayers { val pipLayerList = layers { ComponentNameMatcher.PIP_CONTENT_OVERLAY.layerMatchesAnyOf(it) && it.isVisible } pipLayerList.zipWithNext { previous, current -> // TODO(b/290987990): Add checks for visibleRegion. current.screenBounds.isToTheRightBottom(previous.screenBounds.region, 3) current.screenBounds.notBiggerThan(previous.screenBounds.region) } } flicker.assertLayersEnd { val pipRegion = visibleRegion( ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) check { "height" } .that(pipRegion.region.height) .isLower(startDisplayBounds.height / 2) check { "width" } .that(pipRegion.region.width).isLower(startDisplayBounds.width) } } companion object { /** {@inheritDoc} */ private var startDisplayBounds = Rect.EMPTY /** * Creates the test configurations. * * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and * navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams() = LegacyFlickerTestFactory.nonRotationTests() } } No newline at end of file tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt +15 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,21 @@ constructor( .waitForAndVerify() } fun secondaryActivityEnterPip(wmHelper: WindowManagerStateHelper) { val pipButton = uiDevice.wait( Until.findObject(By.res(getPackage(), "secondary_enter_pip_button")), FIND_TIMEOUT ) require(pipButton != null) { "Can't find enter pip button on screen." } pipButton.click() wmHelper .StateSyncBuilder() .withAppTransitionIdle() .withPipShown() .waitForAndVerify() } /** * Clicks the button to launch a secondary activity with alwaysExpand enabled, which will launch * a fullscreen window on top of the visible region. Loading tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding" android:theme="@style/CutoutShortEdges" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" android:supportsPictureInPicture="true" android:exported="false"/> <activity android:name=".ActivityEmbeddingThirdActivity" Loading tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml +6 −0 Original line number Diff line number Diff line Loading @@ -35,4 +35,10 @@ android:onClick="launchThirdActivity" android:text="Launch a third activity" /> <Button android:id="@+id/secondary_enter_pip_button" android:layout_width="wrap_content" android:layout_height="48dp" android:text="Enter pip" /> </LinearLayout> No newline at end of file Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/SplitScreenUtils.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import com.android.server.wm.flicker.testapp.ActivityOptions import com.android.server.wm.flicker.testapp.ActivityOptions.SplitScreen.Primary import org.junit.Assert.assertNotNull internal object SplitScreenUtils { object SplitScreenUtils { private const val TIMEOUT_MS = 3_000L private const val DRAG_DURATION_MS = 1_000L private const val NOTIFICATION_SCROLLER = "notification_stack_scroller" Loading
tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker.activityembedding import android.platform.test.annotations.Presubmit import android.tools.common.datatypes.Rect import android.tools.common.traces.component.ComponentNameMatcher import android.tools.common.traces.component.ComponentNameMatcher.Companion.TRANSITION_SNAPSHOT import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.LegacyFlickerTest import android.tools.device.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test launching a secondary Activity into Picture-In-Picture mode. * * Setup: Start from a split A|B. * Transition: B enters PIP, observe the window shrink to the bottom right corner on screen. * * To run this test: `atest FlickerTests:SecondaryActivityEnterPipTest` * */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class SecondaryActivityEnterPipTest (flicker: LegacyFlickerTest) : ActivityEmbeddingTestBase(flicker) { override val transition: FlickerBuilder.() -> Unit = { setup { tapl.setExpectedRotationCheckEnabled(false) testApp.launchViaIntent(wmHelper) testApp.launchSecondaryActivity(wmHelper) startDisplayBounds = wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Can't get display bounds") } transitions { testApp.secondaryActivityEnterPip(wmHelper) } teardown { tapl.goHome() testApp.exit(wmHelper) } } /** * Main and secondary activity start from a split each taking half of the screen. */ @Presubmit @Test fun layersStartFromEqualSplit() { flicker.assertLayersStart { val leftLayerRegion = visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) val rightLayerRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) // Compare dimensions of two splits, given we're using default split attributes, // both activities take up the same visible size on the display. check { "height" } .that(leftLayerRegion.region.height).isEqual(rightLayerRegion.region.height) check { "width" } .that(leftLayerRegion.region.width).isEqual(rightLayerRegion.region.width) leftLayerRegion.notOverlaps(rightLayerRegion.region) leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds) } flicker.assertLayersEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Main Activity is visible throughout the transition and becomes fullscreen. */ @Presubmit @Test fun mainActivityWindowBecomesFullScreen() { flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) } flicker.assertWmEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Main Activity is visible throughout the transition and becomes fullscreen. */ @Presubmit @Test fun mainActivityLayerBecomesFullScreen() { flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .then() .isVisible(TRANSITION_SNAPSHOT) .isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .then() .isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) } flicker.assertLayersEnd { visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) .coversExactly(startDisplayBounds) } } /** * Secondary Activity is visible throughout the transition and shrinks to the bottom right * corner. */ @Presubmit @Test fun secondaryWindowShrinks() { flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) } flicker.assertWmEnd { val pipWindowRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) check{"height"} .that(pipWindowRegion.region.height) .isLower(startDisplayBounds.height / 2) check{"width"} .that(pipWindowRegion.region.width).isLower(startDisplayBounds.width) } } /** * During the transition Secondary Activity shrinks to the bottom right corner. */ @Presubmit @Test fun secondaryLayerShrinks() { flicker.assertLayers { val pipLayerList = layers { ComponentNameMatcher.PIP_CONTENT_OVERLAY.layerMatchesAnyOf(it) && it.isVisible } pipLayerList.zipWithNext { previous, current -> // TODO(b/290987990): Add checks for visibleRegion. current.screenBounds.isToTheRightBottom(previous.screenBounds.region, 3) current.screenBounds.notBiggerThan(previous.screenBounds.region) } } flicker.assertLayersEnd { val pipRegion = visibleRegion( ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) check { "height" } .that(pipRegion.region.height) .isLower(startDisplayBounds.height / 2) check { "width" } .that(pipRegion.region.width).isLower(startDisplayBounds.width) } } companion object { /** {@inheritDoc} */ private var startDisplayBounds = Rect.EMPTY /** * Creates the test configurations. * * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and * navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams() = LegacyFlickerTestFactory.nonRotationTests() } } No newline at end of file
tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt +15 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,21 @@ constructor( .waitForAndVerify() } fun secondaryActivityEnterPip(wmHelper: WindowManagerStateHelper) { val pipButton = uiDevice.wait( Until.findObject(By.res(getPackage(), "secondary_enter_pip_button")), FIND_TIMEOUT ) require(pipButton != null) { "Can't find enter pip button on screen." } pipButton.click() wmHelper .StateSyncBuilder() .withAppTransitionIdle() .withPipShown() .waitForAndVerify() } /** * Clicks the button to launch a secondary activity with alwaysExpand enabled, which will launch * a fullscreen window on top of the visible region. Loading
tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding" android:theme="@style/CutoutShortEdges" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" android:supportsPictureInPicture="true" android:exported="false"/> <activity android:name=".ActivityEmbeddingThirdActivity" Loading
tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml +6 −0 Original line number Diff line number Diff line Loading @@ -35,4 +35,10 @@ android:onClick="launchThirdActivity" android:text="Launch a third activity" /> <Button android:id="@+id/secondary_enter_pip_button" android:layout_width="wrap_content" android:layout_height="48dp" android:text="Enter pip" /> </LinearLayout> No newline at end of file