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

Commit 88957856 authored by Ikram Gabiyev's avatar Ikram Gabiyev Committed by Android (Google) Code Review
Browse files

Merge "Implement drag then snap flicker test" into udc-dev

parents cf0fa7da 7789c031
Loading
Loading
Loading
Loading
+95 −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.wm.shell.flicker.pip

import android.platform.test.annotations.Postsubmit
import android.tools.common.Rotation
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.graphics.Rect
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.testapp.ActivityOptions
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized

/**
 * Test the snapping of a PIP window via dragging, releasing, and checking its final location.
 */
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker){
    override val transition: FlickerBuilder.() -> Unit
        get() = {
            val stringExtras: Map<String, String> =
                mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true")

            // cache the starting bounds here
            val startBounds = Rect()

            setup {
                // Launch the PIP activity and wait for it to enter PiP mode
                setRotation(Rotation.ROTATION_0)
                RemoveAllTasksButHomeRule.removeAllTasksButHome()
                pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)

                val initRegion = pipApp.dragPipWindowAwayFromEdge(wmHelper, 50)
                startBounds
                    .set(initRegion.left, initRegion.top, initRegion.right, initRegion.bottom)
            }
            transitions {
                // continue the transition until the PIP snaps
                pipApp.waitForPipToSnapTo(wmHelper, startBounds)
            }
        }

    /** Checks that the visible region area of [pipApp] always moves right during the animation. */
    @Postsubmit
    @Test
    fun pipLayerMovesRight() {
        flicker.assertLayers {
            val pipLayerList = layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
            pipLayerList.zipWithNext { previous, current ->
                current.visibleRegion.isToTheRight(previous.visibleRegion.region)
            }
        }
    }

    companion object {
        /**
         * Creates the test configurations.
         *
         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
         * navigation modes.
         */
        @Parameterized.Parameters(name = "{0}")
        @JvmStatic
        fun getParams(): List<FlickerTest> {
            return FlickerTestFactory.nonRotationTests(
                supportedRotations = listOf(Rotation.ROTATION_0)
            )
        }
    }
}
 No newline at end of file
+67 −2
Original line number Diff line number Diff line
@@ -58,7 +58,51 @@ open class PipAppHelper(instrumentation: Instrumentation) :
    }

    /**
     * Expands the PIP window my using the pinch out gesture.
     * Drags the PIP window away from the screen edge while not crossing the display center.
     *
     * @throws IllegalStateException if default display bounds are not available
     * @return initial bounds of the PIP window
     */
    fun dragPipWindowAwayFromEdge(wmHelper: WindowManagerStateHelper, steps: Int): Rect {
        val initWindowRect = getWindowRect(wmHelper).clone()

        // initial pointer at the center of the window
        val startX = initWindowRect.centerX()
        val y = initWindowRect.centerY()

        val displayRect = wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
                ?: throw IllegalStateException("Default display is null")

        // the offset to the right of the display center to drag the window to
        val offset = 20

        // the actual final x coordinate with the offset included
        // if the pip window is closer to the right edge of the display the offset is positive
        // otherwise the offset is negative
        val endX = displayRect.centerX() + offset * (if (isCloserToRightEdge(wmHelper)) 1 else -1)

        // drag the window to the left but not beyond the center of the display
        uiDevice.drag(startX, y, endX, y, steps)

        return initWindowRect
    }

    /**
     * Returns true if PIP window is closer to the right edge of the display than left.
     *
     * @throws IllegalStateException if default display bounds are not available
     */
    private fun isCloserToRightEdge(wmHelper: WindowManagerStateHelper): Boolean {
        val windowRect = getWindowRect(wmHelper)

        val displayRect = wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
                ?: throw IllegalStateException("Default display is null")

        return windowRect.centerX() > displayRect.centerX()
    }

    /**
     * Expands the PIP window by using the pinch out gesture.
     *
     * @param percent The percentage by which to increase the pip window size.
     * @throws IllegalArgumentException if percentage isn't between 0.0f and 1.0f
@@ -106,7 +150,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
    }

    /**
     * Minimizes the PIP window my using the pinch in gesture.
     * Minimizes the PIP window by using the pinch in gesture.
     *
     * @param percent The percentage by which to decrease the pip window size.
     * @throws IllegalArgumentException if percentage isn't between 0.0f and 1.0f
@@ -307,6 +351,27 @@ open class PipAppHelper(instrumentation: Instrumentation) :
            .waitForAndVerify()
    }

    /**
     * Waits until the PIP window snaps horizontally to the provided bounds.
     *
     * @param finalRightX the final x coordinate of the right edge of the pip window
     */
    fun waitForPipToSnapTo(wmHelper: WindowManagerStateHelper, finalBounds: android.graphics.Rect) {
        wmHelper
            .StateSyncBuilder()
            .add("pipWindowSnapped") {
                val pipAppWindow =
                    it.wmState.visibleWindows.firstOrNull { window ->
                        this.windowMatchesAnyOf(window)
                    }
                        ?: return@add false
                val pipRegionBounds = pipAppWindow.frameRegion.bounds
                return@add pipRegionBounds.left == finalBounds.left &&
                    pipRegionBounds.right == finalBounds.right
            }
            .waitForAndVerify()
    }

    companion object {
        private const val TAG = "PipAppHelper"
        private const val ENTER_PIP_BUTTON_ID = "enter_pip"