Implement flicker test for dragging
Implement a flicker test for the drag gesture in pip Bug: 271868275 Test: atest WMShellFlickerTests:PipDragTest Change-Id: Ieeb1472420173e9b3401d0588c9b6dae6ef59ff3
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.platform.test.annotations.RequiresDevice
|
||||
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
|
||||
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 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 dragging of a PIP window.
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
class PipDragTest(flicker: FlickerTest) : PipTransition(flicker) {
|
||||
private var isDraggedLeft: Boolean = true
|
||||
override val transition: FlickerBuilder.() -> Unit
|
||||
get() = {
|
||||
val stringExtras = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true")
|
||||
|
||||
setup {
|
||||
tapl.setEnableRotation(true)
|
||||
// Launch the PIP activity and wait for it to enter PiP mode
|
||||
RemoveAllTasksButHomeRule.removeAllTasksButHome()
|
||||
pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
|
||||
|
||||
// determine the direction of dragging to test for
|
||||
isDraggedLeft = pipApp.isCloserToRightEdge(wmHelper)
|
||||
}
|
||||
teardown {
|
||||
// release the primary pointer after dragging without release
|
||||
pipApp.releasePipAfterDragging()
|
||||
|
||||
pipApp.exit(wmHelper)
|
||||
tapl.setEnableRotation(false)
|
||||
}
|
||||
transitions {
|
||||
pipApp.dragPipWindowAwayFromEdgeWithoutRelease(wmHelper, 50)
|
||||
}
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun pipLayerMovesAwayFromEdge() {
|
||||
flicker.assertLayers {
|
||||
val pipLayerList = layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
|
||||
pipLayerList.zipWithNext { previous, current ->
|
||||
if (isDraggedLeft) {
|
||||
previous.visibleRegion.isToTheRight(current.visibleRegion.region)
|
||||
} else {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@ import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerCoords;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Injects gestures given an {@link Instrumentation} object.
|
||||
*/
|
||||
@@ -35,6 +37,13 @@ public class GestureHelper {
|
||||
|
||||
private final UiAutomation mUiAutomation;
|
||||
|
||||
/**
|
||||
* Primary pointer should be cached here for separate release
|
||||
*/
|
||||
@Nullable private PointerProperties mPrimaryPtrProp;
|
||||
@Nullable private PointerCoords mPrimaryPtrCoord;
|
||||
private long mPrimaryPtrDownTime;
|
||||
|
||||
/**
|
||||
* A pair of floating point values.
|
||||
*/
|
||||
@@ -52,6 +61,52 @@ public class GestureHelper {
|
||||
mUiAutomation = instrumentation.getUiAutomation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a series of {@link MotionEvent}s to simulate a drag gesture without pointer release.
|
||||
*
|
||||
* Simulates a drag gesture without releasing the primary pointer. The primary pointer info
|
||||
* will be cached for potential release later on by {@code releasePrimaryPointer()}
|
||||
*
|
||||
* @param startPoint initial coordinates of the primary pointer
|
||||
* @param endPoint final coordinates of the primary pointer
|
||||
* @param steps number of steps to take to animate dragging
|
||||
* @return true if gesture is injected successfully
|
||||
*/
|
||||
public boolean dragWithoutRelease(@NonNull Tuple startPoint,
|
||||
@NonNull Tuple endPoint, int steps) {
|
||||
PointerProperties ptrProp = getPointerProp(0, MotionEvent.TOOL_TYPE_FINGER);
|
||||
PointerCoords ptrCoord = getPointerCoord(startPoint.x, startPoint.y, 1, 1);
|
||||
|
||||
PointerProperties[] ptrProps = new PointerProperties[] { ptrProp };
|
||||
PointerCoords[] ptrCoords = new PointerCoords[] { ptrCoord };
|
||||
|
||||
long downTime = SystemClock.uptimeMillis();
|
||||
|
||||
if (!primaryPointerDown(ptrProp, ptrCoord, downTime)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// cache the primary pointer info for later potential release
|
||||
mPrimaryPtrProp = ptrProp;
|
||||
mPrimaryPtrCoord = ptrCoord;
|
||||
mPrimaryPtrDownTime = downTime;
|
||||
|
||||
return movePointers(ptrProps, ptrCoords, new Tuple[] { endPoint }, downTime, steps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release primary pointer if previous gesture has cached the primary pointer info.
|
||||
*
|
||||
* @return true if the release was injected successfully
|
||||
*/
|
||||
public boolean releasePrimaryPointer() {
|
||||
if (mPrimaryPtrProp != null && mPrimaryPtrCoord != null) {
|
||||
return primaryPointerUp(mPrimaryPtrProp, mPrimaryPtrCoord, mPrimaryPtrDownTime);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a series of {@link MotionEvent} objects to simulate a pinch gesture.
|
||||
*
|
||||
|
||||
@@ -57,6 +57,43 @@ open class PipAppHelper(instrumentation: Instrumentation) :
|
||||
obj.click()
|
||||
}
|
||||
|
||||
/**
|
||||
* Drags the PIP window to the provided final coordinates without releasing the pointer.
|
||||
*/
|
||||
fun dragPipWindowAwayFromEdgeWithoutRelease(
|
||||
wmHelper: WindowManagerStateHelper,
|
||||
steps: Int
|
||||
) {
|
||||
val initWindowRect = getWindowRect(wmHelper).clone()
|
||||
|
||||
// initial pointer at the center of the window
|
||||
val initialCoord = GestureHelper.Tuple(initWindowRect.centerX().toFloat(),
|
||||
initWindowRect.centerY().toFloat())
|
||||
|
||||
// the offset to the right (or left) of the window center to drag the window to
|
||||
val offset = 50
|
||||
|
||||
// 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 negative
|
||||
// otherwise the offset is positive
|
||||
val endX = initWindowRect.centerX() +
|
||||
offset * (if (isCloserToRightEdge(wmHelper)) -1 else 1)
|
||||
val finalCoord = GestureHelper.Tuple(endX.toFloat(), initWindowRect.centerY().toFloat())
|
||||
|
||||
// drag to the final coordinate
|
||||
gestureHelper.dragWithoutRelease(initialCoord, finalCoord, steps)
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the primary pointer.
|
||||
*
|
||||
* Injects the release of the primary pointer if the primary pointer info was cached after
|
||||
* another gesture was injected without pointer release.
|
||||
*/
|
||||
fun releasePipAfterDragging() {
|
||||
gestureHelper.releasePrimaryPointer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Drags the PIP window away from the screen edge while not crossing the display center.
|
||||
*
|
||||
@@ -72,10 +109,10 @@ open class PipAppHelper(instrumentation: Instrumentation) :
|
||||
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
|
||||
// the offset to the right (or left) of the display center to drag the window to
|
||||
val offset = 20
|
||||
|
||||
// the actual final x coordinate with the offset included
|
||||
// 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)
|
||||
|
||||
Reference in New Issue
Block a user