Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f296d244 authored by Charles Chen's avatar Charles Chen
Browse files

Add flicker tests for non-match parent enter PIP animation

Bug: 356277166
Test: atest BottomHalfAutoEnterPipOnGoToHomeTest BottomHalfEnterPipOnUserLeaveHintTest
Test: BottomHalfEnterPipViaAppUiButtonTest
Flag: com.android.window.flags.better_support_non_match_parent_activity

Change-Id: If934ee3f7f951fc1716dcc0231cb0365923e752d
parent 767ff220
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -115,6 +115,11 @@ test_module_config {
        "com.android.wm.shell.flicker.pip.PipPinchInTest",
        "com.android.wm.shell.flicker.pip.SetRequestedOrientationWhilePinned",
        "com.android.wm.shell.flicker.pip.ShowPipAndRotateDisplay",
        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfAutoEnterPipOnGoToHomeTest",
        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipOnUserLeaveHintTest",
        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipViaAppUiButtonTest",
        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaExpandButtonTest",
        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaIntentTest",
    ],
    test_suites: ["device-tests"],
}
@@ -266,12 +271,7 @@ test_module_config {
    test_suites: ["device-tests"],
}

test_module_config {
    name: "WMShellFlickerTestsPip-nonMatchParent",
    base: "WMShellFlickerTestsPip",
    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.*"],
    test_suites: ["device-tests"],
}
// Not-match Parent test cases

test_module_config {
    name: "WMShellFlickerTestsPip-BottomHalfExitPipToAppViaExpandButtonTest",
@@ -287,5 +287,26 @@ test_module_config {
    test_suites: ["device-tests"],
}

test_module_config {
    name: "WMShellFlickerTestsPip-BottomHalfAutoEnterPipOnGoToHomeTest",
    base: "WMShellFlickerTestsPip",
    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfAutoEnterPipOnGoToHomeTest"],
    test_suites: ["device-tests"],
}

test_module_config {
    name: "WMShellFlickerTestsPip-BottomHalfEnterPipOnUserLeaveHintTest",
    base: "WMShellFlickerTestsPip",
    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipOnUserLeaveHintTest"],
    test_suites: ["device-tests"],
}

test_module_config {
    name: "WMShellFlickerTestsPip-BottomHalfEnterPipViaAppUiButtonTest",
    base: "WMShellFlickerTestsPip",
    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipViaAppUiButtonTest"],
    test_suites: ["device-tests"],
}

// End breakdowns for WMShellFlickerTestsPip module
////////////////////////////////////////////////////////////////////////////////
+1 −26
Original line number Diff line number Diff line
@@ -24,20 +24,16 @@ import android.platform.test.annotations.RequiresFlagsDisabled
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder
import android.tools.flicker.subject.exceptions.IncorrectRegionException
import android.tools.flicker.subject.layers.LayerSubject
import com.android.server.wm.flicker.helpers.PipAppHelper
import com.android.wm.shell.Flags
import com.android.wm.shell.flicker.pip.common.EnterPipTransition
import com.android.wm.shell.flicker.pip.common.widthNotSmallerThan
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
import kotlin.math.abs


/**
 * Test entering pip from an app via auto-enter property when navigating to home.
@@ -77,22 +73,6 @@ open class AutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) : EnterPipTran
        }
    }

    override val defaultTeardown: FlickerBuilder.() -> Unit = { teardown { pipApp.exit(wmHelper) } }

    private val widthNotSmallerThan: LayerSubject.(LayerSubject) -> Unit = {
        val width = visibleRegion.region.bounds.width()
        val otherWidth = it.visibleRegion.region.bounds.width()
        if (width < otherWidth && abs(width - otherWidth) > EPSILON) {
            val errorMsgBuilder =
                ExceptionMessageBuilder()
                    .forSubject(this)
                    .forIncorrectRegion("width. $width smaller than $otherWidth")
                    .setExpected(width)
                    .setActual(otherWidth)
            throw IncorrectRegionException(errorMsgBuilder)
        }
    }

    @Postsubmit
    @Test
    override fun pipLayerReduces() {
@@ -161,9 +141,4 @@ open class AutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) : EnterPipTran
    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
        super.visibleLayersShownMoreThanOneConsecutiveEntry()
    }

    companion object {
        // TODO(b/363080056): A margin of error allowed on certain layer size calculations.
        const val EPSILON = 1
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ class EnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) : EnterPipTransiti
        super.pipOverlayLayerAppearThenDisappear()
    }

    // TODO(b/385086051): check if we can remove optional = true in the test.
    @Presubmit
    @Test
    fun pipAppWindowVisibleChanges() {
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.wm.shell.flicker.pip.common

import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder
import android.tools.flicker.subject.exceptions.IncorrectRegionException
import android.tools.flicker.subject.layers.LayerSubject
import kotlin.math.abs

// TODO(b/363080056): A margin of error allowed on certain layer size calculations.
const val EPSILON = 1

internal val widthNotSmallerThan: LayerSubject.(LayerSubject) -> Unit = {
    val width = visibleRegion.region.bounds.width()
    val otherWidth = it.visibleRegion.region.bounds.width()
    if (width < otherWidth && abs(width - otherWidth) > EPSILON) {
        val errorMsgBuilder =
            ExceptionMessageBuilder()
                .forSubject(this)
                .forIncorrectRegion("width. $width smaller than $otherWidth")
                .setExpected(width)
                .setActual(otherWidth)
        throw IncorrectRegionException(errorMsgBuilder)
    }
}
 No newline at end of file
+170 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.wm.shell.flicker.pip.nonmatchparent

import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import androidx.test.filters.FlakyTest
import com.android.window.flags.Flags
import com.android.wm.shell.flicker.pip.common.widthNotSmallerThan
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized

/**
 * Test entering pip from an app with non-match parent layout via auto-enter property when
 * navigating to home.
 *
 * To run this test: `atest WMShellFlickerTestsPip:BottomHalfAutoEnterPipOnGoToHomeTest`
 *
 * Actions:
 * ```
 *     Launch [BottomHalfPipLaunchingActivity] in full screen
 *     Launch [BottomHalfPipActivity] with bottom half layout
 *     Select "Auto-enter PiP" radio button
 *     Press Home button or swipe up to go Home and put [BottomHalfPipActivity] in pip mode
 * ```
 *
 * Notes:
 * ```
 *     1. All assertions are inherited from [EnterPipTest]
 *     2. Part of the test setup occurs automatically via
 *        [android.tools.flicker.legacy.runner.TransitionRunner],
 *        including configuring navigation mode, initial orientation and ensuring no
 *        apps are running before setup
 * ```
 */
// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2.
@RequiresFlagsDisabled(com.android.wm.shell.Flags.FLAG_ENABLE_PIP2)
@RequiresFlagsEnabled(Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY)
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class BottomHalfAutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) :
    BottomHalfEnterPipTransition(flicker) {

    override val thisTransition: FlickerBuilder.() -> Unit = { transitions {
        tapl.goHome()
        pipApp.waitForPip(wmHelper)
    } }

    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
        setup {
            pipApp.launchViaIntent(wmHelper)
            pipApp.enableAutoEnterForPipActivity()
        }
    }

    @FlakyTest(bugId = 289943985)
    @Test
    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
        super.visibleLayersShownMoreThanOneConsecutiveEntry()
    }

    /* Gestural Navigation */

    /**
     * Checks that [pipApp] window's width is first decreasing then increasing.
     *
     * In gestural navigation mode, auto entering PiP can initially make the layer smaller before it
     * gets larger.
     * This tests verifies the width of the PiP layer first decreases and then increases due to
     * size and scale animations going to different directions.
     *
     * Note that we still allow a margin of error of 1px, since around the time
     * of handoff between gesture nav task view simulator and
     * SwipePipToHomeAnimator, crop can get a bit smaller and scale can get a
     * bit larger if swiped aggressively - this can produce off-by-1 errors for
     * width too.
     */
    @Postsubmit
    @Test
    fun pipLayerWidthDecreasesThenIncreases() {
        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
        flicker.assertLayers {
            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
            var previousLayer = pipLayerList[0]
            var currentLayer = previousLayer
            var i = 0
            invoke("layer area is decreasing") {
                if (i < pipLayerList.size - 1) {
                    previousLayer = currentLayer
                    currentLayer = pipLayerList[++i]
                    previousLayer.widthNotSmallerThan(currentLayer)
                }
            }.then().invoke("layer are is increasing", true /* isOptional */) {
                if (i < pipLayerList.size - 1) {
                    previousLayer = currentLayer
                    currentLayer = pipLayerList[++i]
                    currentLayer.widthNotSmallerThan(previousLayer)
                }
            }
        }
    }

    /* 3-button Navigation */

    /**
     * The PIP layer reduces continuously in 3-Button navigation mode.
     */
    @Postsubmit
    @Test
    override fun pipLayerReduces() {
        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
        flicker.assertLayers {
            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
            pipLayerList.zipWithNext { previous, current ->
                current.visibleRegion.notBiggerThan(previous.visibleRegion.region)
            }
        }
    }

    /** Checks that [pipApp] window is animated towards default position in right bottom corner */
    @FlakyTest(bugId = 255578530)
    @Test
    fun pipLayerMovesTowardsRightBottomCorner() {
        // in gestural nav the swipe makes PiP first go upwards
        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
        flicker.assertLayers {
            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
            // Pip animates towards the right bottom corner, but because it is being resized at the
            // same time, it is possible it shrinks first quickly below the default position and get
            // moved up after that in just few last frames
            pipLayerList.zipWithNext { previous, current ->
                current.visibleRegion.isToTheRightBottom(previous.visibleRegion.region, 3)
            }
        }
    }

    @Presubmit
    @Test
    override fun focusChanges() {
        // in gestural nav the focus goes to different activity on swipe up
        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
        super.focusChanges()
    }
}
Loading