Merge "Implement flicker test for dragging" into udc-dev

This commit is contained in:
Ikram Gabiyev
2023-03-29 01:30:47 +00:00
committed by Android (Google) Code Review
3 changed files with 189 additions and 2 deletions

View File

@@ -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()
}
}
}

View File

@@ -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.
*

View File

@@ -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)