Commit eddea9d9 authored by bsheedy's avatar bsheedy Committed by Commit Bot

Reduce VR gamepad test flakiness

Reduces the flakiness of testControllerClicksRegisteredOnDaydream in two
ways:
1. Adds code to handle GVR briefly disconnecting then reconnecting the
    controller, which caused us to receive multiple gamepadconnected
    events.
2. Ensures any input that was sent to register the gamepad is drained
    before actually starting the test, as slow intents could be received
    later and cause the test to end earlier than expected.

Bug: 831589
Change-Id: I8041030ef6ec177ad47216eb1c1ea9e0f875e7c4
Reviewed-on: https://chromium-review.googlesource.com/1012439Reviewed-by: default avatarYash Malik <ymalik@chromium.org>
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551421}
parent d7029356
......@@ -14,6 +14,7 @@ import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_V
import android.app.Activity;
import android.os.Build;
import android.os.SystemClock;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.view.MotionEvent;
import android.view.View;
......@@ -157,7 +158,7 @@ public class WebVrInputTest {
* Tests that Daydream controller clicks are registered as gamepad button pressed.
*/
@Test
@MediumTest
@LargeTest
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
@VrActivityRestriction({VrActivityRestriction.SupportedActivity.ALL})
public void testControllerClicksRegisteredOnDaydream() throws InterruptedException {
......@@ -165,18 +166,12 @@ public class WebVrInputTest {
mVrTestFramework.loadUrlAndAwaitInitialization(
VrTestFramework.getHtmlTestFile("test_gamepad_button"), PAGE_LOAD_TIMEOUT_S);
// Wait to enter VR
VrTransitionUtils.enterPresentationAndWait(
mVrTestFramework.getFirstTabCvc(), mVrTestFramework.getFirstTabWebContents());
VrTransitionUtils.enterPresentationOrFail(mVrTestFramework.getFirstTabCvc());
// The Gamepad API can flakily fail to detect the gamepad from a single button press, so
// spam it with button presses
boolean controllerConnected = false;
for (int i = 0; i < 10; i++) {
// The Gamepad API doesn't like detecting pressReleaseTouchpadButton() as it's too fast,
// so manually send the up and down events with a delay
controller.sendClickButtonToggleEvent();
SystemClock.sleep(100);
controller.sendClickButtonToggleEvent();
SystemClock.sleep(100);
controller.performControllerClick();
if (VrTestFramework
.runJavaScriptOrFail("index != -1", POLL_TIMEOUT_SHORT_MS,
mVrTestFramework.getFirstTabWebContents())
......@@ -186,6 +181,11 @@ public class WebVrInputTest {
}
}
Assert.assertTrue("Gamepad API detected controller", controllerConnected);
// It's possible for input to get backed up if the emulated controller is being slow, so
// ensure that any outstanding output has been received before starting by waiting for
// 60 frames (1 second) of not receiving input.
VrTestFramework.pollJavaScriptBoolean("isInputDrained()", POLL_TIMEOUT_LONG_MS,
mVrTestFramework.getFirstTabWebContents());
// Have a separate start condition so that the above presses/releases don't get
// accidentally detected during the actual test
VrTestFramework.runJavaScriptOrFail("canStartTest = true;", POLL_TIMEOUT_SHORT_MS,
......@@ -269,8 +269,7 @@ public class WebVrInputTest {
VrTestFramework.runJavaScriptOrFail("canStartTest = true;", POLL_TIMEOUT_SHORT_MS,
mVrTestFramework.getFirstTabWebContents());
// Wait to enter VR
VrTransitionUtils.enterPresentationAndWait(
mVrTestFramework.getFirstTabCvc(), mVrTestFramework.getFirstTabWebContents());
VrTransitionUtils.enterPresentationOrFail(mVrTestFramework.getFirstTabCvc());
int x = mVrTestFramework.getFirstTabContentView().getWidth() / 2;
int y = mVrTestFramework.getFirstTabContentView().getHeight() / 2;
// TODO(mthiesse, https://crbug.com/758374): Injecting touch events into the root GvrLayout
......
......@@ -15,21 +15,44 @@ View.
<script src="../resources/webvr_boilerplate.js"></script>
<script>
var t = async_test("Screen taps/clicks registered when in VR");
window.addEventListener("vrdisplaypresentchange",
() => {finishJavaScriptStep();}, false);
var pressed = false;
var index = -1;
var canStartTest = false;
var frameCounter = 0;
var lastInputChangeFrame = 0;
var lastInputValue = false;
window.addEventListener("gamepadconnected", function(e) {
t.step( () => {
assert_equals(index, -1, "Should only receive gamepadconnected once");
assert_equals(index, -1, "Should only have one connected controller");
});
index = e.gamepad.index;
});
// GVR can very briefly disconnect then reconnect the controller, so
// handle that case.
window.addEventListener("gamepaddisconnected", function(e) {
index = -1;
});
// Returns true if no input has been received for 60 frames.
function isInputDrained() {
return frameCounter - lastInputChangeFrame > 60;
}
onPresentingAnimationFrameCallback = function() {
if (index == -1) return;
if (!canStartTest) return;
frameCounter++;
var gp = navigator.getGamepads()[index];
// This can happen if the controller has been briefly disconnected.
if (gp === null) return;
if (!canStartTest) {
if (gp.buttons[0].pressed != lastInputValue) {
lastInputChangeFrame = frameCounter;
}
lastInputValue = gp.buttons[0].pressed;
return;
}
if (!pressed && gp.buttons[0].pressed == true) {
pressed = true;
finishJavaScriptStep();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment