Commit 2ec0b0c0 authored by aicommander's avatar aicommander Committed by Commit bot

Gamepad: Improve gamepad mapping code and unknown gamepad heuristics

This CL modifies the GamepadMappings class to use subclasses
for mappings rather than static methods. The advantage is that
the unknown gamepad mapping can keep state around that allows
it to create heuristic mappings at GamepadDevice constrution
time. This allows stable mappings that don't depend on input
to decide correctly. This also means we aren't doing string
parsing on each gamepad event anymore.

With this change, Moga Pro, Nexus Player (ASUS) Gamepad, and Razer
Serval controllers are working correctly without explict mappings.

Before the change, the D-Pad on Moga, Serval, and ASUS Gamepad were
non-functional. The triggers on the Moga didn't work at all, and the
Serval and ASUS Gamepad's triggers were swapped with the shoulder
buttons.

TEST=http://html5gamepad.com/
BUG=615656

Review-Url: https://codereview.chromium.org/2071223002
Cr-Commit-Position: refs/heads/master@{#419372}
parent 3c3a4409
...@@ -35,8 +35,6 @@ class GamepadDevice { ...@@ -35,8 +35,6 @@ class GamepadDevice {
private int mDeviceIndex; private int mDeviceIndex;
// Last time the data for this gamepad was updated. // Last time the data for this gamepad was updated.
private long mTimestamp; private long mTimestamp;
// If this gamepad is mapped to standard gamepad?
private boolean mIsStandardGamepad;
// Array of values for all axes of the gamepad. // Array of values for all axes of the gamepad.
// All axis values must be linearly normalized to the range [-1.0 .. 1.0]. // All axis values must be linearly normalized to the range [-1.0 .. 1.0].
...@@ -59,6 +57,9 @@ class GamepadDevice { ...@@ -59,6 +57,9 @@ class GamepadDevice {
// Array of axes ids. // Array of axes ids.
private int[] mAxes; private int[] mAxes;
// Mappings to canonical gamepad
private GamepadMappings mMappings;
GamepadDevice(int index, InputDevice inputDevice) { GamepadDevice(int index, InputDevice inputDevice) {
mDeviceIndex = index; mDeviceIndex = index;
mDeviceId = inputDevice.getId(); mDeviceId = inputDevice.getId();
...@@ -75,14 +76,14 @@ class GamepadDevice { ...@@ -75,14 +76,14 @@ class GamepadDevice {
mAxes[i++] = axis; mAxes[i++] = axis;
} }
} }
mMappings = GamepadMappings.getMappings(mDeviceName, mAxes);
} }
/** /**
* Updates the axes and buttons maping of a gamepad device to a standard gamepad format. * Updates the axes and buttons maping of a gamepad device to a standard gamepad format.
*/ */
public void updateButtonsAndAxesMapping() { public void updateButtonsAndAxesMapping() {
mIsStandardGamepad = GamepadMappings.mapToStandardGamepad( mMappings.mapToStandardGamepad(mAxisValues, mButtonsValues, mRawAxes, mRawButtons);
mAxisValues, mButtonsValues, mRawAxes, mRawButtons, mDeviceName);
} }
/** /**
...@@ -96,7 +97,7 @@ class GamepadDevice { ...@@ -96,7 +97,7 @@ class GamepadDevice {
* @return Mapping status of the gamepad device. * @return Mapping status of the gamepad device.
*/ */
public boolean isStandardGamepad() { public boolean isStandardGamepad() {
return mIsStandardGamepad; return mMappings.isStandard();
} }
/** /**
......
...@@ -14,7 +14,7 @@ import org.chromium.base.annotations.JNINamespace; ...@@ -14,7 +14,7 @@ import org.chromium.base.annotations.JNINamespace;
* Class to manage mapping information related to each supported gamepad controller device. * Class to manage mapping information related to each supported gamepad controller device.
*/ */
@JNINamespace("content") @JNINamespace("content")
class GamepadMappings { abstract class GamepadMappings {
@VisibleForTesting @VisibleForTesting
static final String NVIDIA_SHIELD_DEVICE_NAME_PREFIX = "NVIDIA Corporation NVIDIA Controller"; static final String NVIDIA_SHIELD_DEVICE_NAME_PREFIX = "NVIDIA Corporation NVIDIA Controller";
@VisibleForTesting @VisibleForTesting
...@@ -26,29 +26,37 @@ class GamepadMappings { ...@@ -26,29 +26,37 @@ class GamepadMappings {
@VisibleForTesting @VisibleForTesting
static final String AMAZON_FIRE_DEVICE_NAME = "Amazon Fire Game Controller"; static final String AMAZON_FIRE_DEVICE_NAME = "Amazon Fire Game Controller";
public static boolean mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons, public static GamepadMappings getMappings(String deviceName, int[] axes) {
float[] rawAxes, float[] rawButtons, String deviceName) { if (deviceName.startsWith(NVIDIA_SHIELD_DEVICE_NAME_PREFIX)
if (deviceName.startsWith(NVIDIA_SHIELD_DEVICE_NAME_PREFIX)) { || deviceName.equals(MICROSOFT_XBOX_PAD_DEVICE_NAME)) {
mapShieldGamepad(mappedButtons, rawButtons, mappedAxes, rawAxes); return new XboxCompatibleGamepadMappings();
return true;
} else if (deviceName.equals(MICROSOFT_XBOX_PAD_DEVICE_NAME)) {
mapXBox360Gamepad(mappedButtons, rawButtons, mappedAxes, rawAxes);
return true;
} else if (deviceName.equals(PS3_SIXAXIS_DEVICE_NAME)) { } else if (deviceName.equals(PS3_SIXAXIS_DEVICE_NAME)) {
mapPS3SixAxisGamepad(mappedButtons, rawButtons, mappedAxes, rawAxes); return new PS3SixAxisGamepadMappings();
return true;
} else if (deviceName.equals(SAMSUNG_EI_GP20_DEVICE_NAME)) { } else if (deviceName.equals(SAMSUNG_EI_GP20_DEVICE_NAME)) {
mapSamsungEIGP20Gamepad(mappedButtons, rawButtons, mappedAxes, rawAxes); return new SamsungEIGP20GamepadMappings();
return true;
} else if (deviceName.equals(AMAZON_FIRE_DEVICE_NAME)) { } else if (deviceName.equals(AMAZON_FIRE_DEVICE_NAME)) {
mapAmazonFireGamepad(mappedButtons, rawButtons, mappedAxes, rawAxes); return new AmazonFireGamepadMappings();
return true;
} }
mapUnknownGamepad(mappedButtons, rawButtons, mappedAxes, rawAxes); return new UnknownGamepadMappings(axes);
return false; }
/**
* Method that specifies whether the mappings are standard or not.
* It should be overridden in subclasses that don't provide standard
* mappings.
*/
public boolean isStandard() {
return true;
} }
/**
* Method implemented by subclasses to perform mapping from raw axes and buttons
* to canonical axes and buttons.
*/
public abstract void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
float[] rawAxes, float[] rawButtons);
private static void mapCommonXYABButtons(float[] mappedButtons, float[] rawButtons) { private static void mapCommonXYABButtons(float[] mappedButtons, float[] rawButtons) {
float a = rawButtons[KeyEvent.KEYCODE_BUTTON_A]; float a = rawButtons[KeyEvent.KEYCODE_BUTTON_A];
float b = rawButtons[KeyEvent.KEYCODE_BUTTON_B]; float b = rawButtons[KeyEvent.KEYCODE_BUTTON_B];
...@@ -76,7 +84,14 @@ class GamepadMappings { ...@@ -76,7 +84,14 @@ class GamepadMappings {
mappedButtons[CanonicalButtonIndex.RIGHT_THUMBSTICK] = thumbR; mappedButtons[CanonicalButtonIndex.RIGHT_THUMBSTICK] = thumbR;
} }
private static void mapCommonTriggerButtons(float[] mappedButtons, float[] rawButtons) { /**
* Method for mapping the L1/R1 buttons to lower shoulder buttons, rather than
* upper shoulder as the user would normally expect. Please think twice before
* using this, as it can easily confuse the user. It is only really useful if
* the controller completely lacks a second set of shoulder buttons.
*/
private static void mapUpperTriggerButtonsToBottomShoulder(float[] mappedButtons,
float[] rawButtons) {
float l1 = rawButtons[KeyEvent.KEYCODE_BUTTON_L1]; float l1 = rawButtons[KeyEvent.KEYCODE_BUTTON_L1];
float r1 = rawButtons[KeyEvent.KEYCODE_BUTTON_R1]; float r1 = rawButtons[KeyEvent.KEYCODE_BUTTON_R1];
mappedButtons[CanonicalButtonIndex.LEFT_TRIGGER] = l1; mappedButtons[CanonicalButtonIndex.LEFT_TRIGGER] = l1;
...@@ -116,13 +131,6 @@ class GamepadMappings { ...@@ -116,13 +131,6 @@ class GamepadMappings {
mappedAxes[CanonicalAxisIndex.RIGHT_STICK_Y] = rawAxes[MotionEvent.AXIS_RZ]; mappedAxes[CanonicalAxisIndex.RIGHT_STICK_Y] = rawAxes[MotionEvent.AXIS_RZ];
} }
private static void mapTriggerAxexToShoulderButtons(float[] mappedButtons, float[] rawAxes) {
float lTrigger = rawAxes[MotionEvent.AXIS_LTRIGGER];
float rTrigger = rawAxes[MotionEvent.AXIS_RTRIGGER];
mappedButtons[CanonicalButtonIndex.LEFT_SHOULDER] = lTrigger;
mappedButtons[CanonicalButtonIndex.RIGHT_SHOULDER] = rTrigger;
}
private static void mapPedalAxesToBottomShoulder(float[] mappedButtons, float[] rawAxes) { private static void mapPedalAxesToBottomShoulder(float[] mappedButtons, float[] rawAxes) {
float lTrigger = rawAxes[MotionEvent.AXIS_BRAKE]; float lTrigger = rawAxes[MotionEvent.AXIS_BRAKE];
float rTrigger = rawAxes[MotionEvent.AXIS_GAS]; float rTrigger = rawAxes[MotionEvent.AXIS_GAS];
...@@ -137,6 +145,14 @@ class GamepadMappings { ...@@ -137,6 +145,14 @@ class GamepadMappings {
mappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER] = rTrigger; mappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER] = rTrigger;
} }
private static void mapLowerTriggerButtonsToBottomShoulder(float[] mappedButtons,
float[] rawButtons) {
float l2 = rawButtons[KeyEvent.KEYCODE_BUTTON_L2];
float r2 = rawButtons[KeyEvent.KEYCODE_BUTTON_R2];
mappedButtons[CanonicalButtonIndex.LEFT_TRIGGER] = l2;
mappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER] = r2;
}
@VisibleForTesting @VisibleForTesting
static float negativeAxisValueAsButton(float input) { static float negativeAxisValueAsButton(float input) {
return (input < -0.5f) ? 1.f : 0.f; return (input < -0.5f) ? 1.f : 0.f;
...@@ -156,12 +172,15 @@ class GamepadMappings { ...@@ -156,12 +172,15 @@ class GamepadMappings {
mappedButtons[CanonicalButtonIndex.DPAD_DOWN] = positiveAxisValueAsButton(hatY); mappedButtons[CanonicalButtonIndex.DPAD_DOWN] = positiveAxisValueAsButton(hatY);
} }
private static class AmazonFireGamepadMappings extends GamepadMappings {
/** /**
* Method for mapping Amazon Fire gamepad axis and button values * Method for mapping Amazon Fire gamepad axis and button values
* to standard gamepad button and axes values. * to standard gamepad button and axes values.
*/ */
private static void mapAmazonFireGamepad( @Override
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) { public void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
float[] rawAxes, float[] rawButtons) {
mapCommonXYABButtons(mappedButtons, rawButtons); mapCommonXYABButtons(mappedButtons, rawButtons);
mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons); mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons);
mapCommonThumbstickButtons(mappedButtons, rawButtons); mapCommonThumbstickButtons(mappedButtons, rawButtons);
...@@ -172,13 +191,17 @@ class GamepadMappings { ...@@ -172,13 +191,17 @@ class GamepadMappings {
mapXYAxes(mappedAxes, rawAxes); mapXYAxes(mappedAxes, rawAxes);
mapZAndRZAxesToRightStick(mappedAxes, rawAxes); mapZAndRZAxesToRightStick(mappedAxes, rawAxes);
} }
}
private static class XboxCompatibleGamepadMappings extends GamepadMappings {
/** /**
* Method for mapping Nvidia gamepad axis and button values * Method for mapping Xbox 360-compatible gamepad axis and button values
* to standard gamepad button and axes values. * to standard gamepad button and axes values.
*/ */
private static void mapShieldGamepad( @Override
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) { public void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
float[] rawAxes, float[] rawButtons) {
mapCommonXYABButtons(mappedButtons, rawButtons); mapCommonXYABButtons(mappedButtons, rawButtons);
mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons); mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons);
mapCommonThumbstickButtons(mappedButtons, rawButtons); mapCommonThumbstickButtons(mappedButtons, rawButtons);
...@@ -189,19 +212,17 @@ class GamepadMappings { ...@@ -189,19 +212,17 @@ class GamepadMappings {
mapXYAxes(mappedAxes, rawAxes); mapXYAxes(mappedAxes, rawAxes);
mapZAndRZAxesToRightStick(mappedAxes, rawAxes); mapZAndRZAxesToRightStick(mappedAxes, rawAxes);
} }
}
private static class PS3SixAxisGamepadMappings extends GamepadMappings {
/** /**
* Method for mapping Microsoft XBox 360 gamepad axis and button values * Method for mapping PS3 gamepad axis and button values
* to standard gamepad button and axes values. * to standard gamepad button and axes values.
*/ */
private static void mapXBox360Gamepad( @Override
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) { public void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
// These are actually mapped the same way in Android. float[] rawAxes, float[] rawButtons) {
mapShieldGamepad(mappedButtons, rawButtons, mappedAxes, rawAxes);
}
private static void mapPS3SixAxisGamepad(
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) {
// On PS3 X/Y has higher priority. // On PS3 X/Y has higher priority.
float a = rawButtons[KeyEvent.KEYCODE_BUTTON_A]; float a = rawButtons[KeyEvent.KEYCODE_BUTTON_A];
float b = rawButtons[KeyEvent.KEYCODE_BUTTON_B]; float b = rawButtons[KeyEvent.KEYCODE_BUTTON_B];
...@@ -212,20 +233,28 @@ class GamepadMappings { ...@@ -212,20 +233,28 @@ class GamepadMappings {
mappedButtons[CanonicalButtonIndex.TERTIARY] = a; mappedButtons[CanonicalButtonIndex.TERTIARY] = a;
mappedButtons[CanonicalButtonIndex.QUATERNARY] = b; mappedButtons[CanonicalButtonIndex.QUATERNARY] = b;
mapCommonTriggerButtons(mappedButtons, rawButtons); mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons);
mapCommonThumbstickButtons(mappedButtons, rawButtons); mapCommonThumbstickButtons(mappedButtons, rawButtons);
mapCommonDpadButtons(mappedButtons, rawButtons); mapCommonDpadButtons(mappedButtons, rawButtons);
mapCommonStartSelectMetaButtons(mappedButtons, rawButtons); mapCommonStartSelectMetaButtons(mappedButtons, rawButtons);
mapTriggerAxexToShoulderButtons(mappedButtons, rawAxes); mapTriggerAxesToBottomShoulder(mappedButtons, rawAxes);
mapXYAxes(mappedAxes, rawAxes); mapXYAxes(mappedAxes, rawAxes);
mapZAndRZAxesToRightStick(mappedAxes, rawAxes); mapZAndRZAxesToRightStick(mappedAxes, rawAxes);
} }
}
private static void mapSamsungEIGP20Gamepad( private static class SamsungEIGP20GamepadMappings extends GamepadMappings {
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) {
/**
* Method for mapping PS3 gamepad axis and button values
* to standard gamepad button and axes values.
*/
@Override
public void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
float[] rawAxes, float[] rawButtons) {
mapCommonXYABButtons(mappedButtons, rawButtons); mapCommonXYABButtons(mappedButtons, rawButtons);
mapCommonTriggerButtons(mappedButtons, rawButtons); mapUpperTriggerButtonsToBottomShoulder(mappedButtons, rawButtons);
mapCommonThumbstickButtons(mappedButtons, rawButtons); mapCommonThumbstickButtons(mappedButtons, rawButtons);
mapCommonStartSelectMetaButtons(mappedButtons, rawButtons); mapCommonStartSelectMetaButtons(mappedButtons, rawButtons);
mapHatAxisToDpadButtons(mappedButtons, rawAxes); mapHatAxisToDpadButtons(mappedButtons, rawAxes);
...@@ -233,21 +262,92 @@ class GamepadMappings { ...@@ -233,21 +262,92 @@ class GamepadMappings {
mapXYAxes(mappedAxes, rawAxes); mapXYAxes(mappedAxes, rawAxes);
mapRXAndRYAxesToRightStick(mappedAxes, rawAxes); mapRXAndRYAxesToRightStick(mappedAxes, rawAxes);
} }
}
/** private static class UnknownGamepadMappings extends GamepadMappings {
* Method for mapping Unkown gamepad axis and button values private int mLeftTriggerAxis = -1;
* to standard gamepad button and axes values. private int mRightTriggerAxis = -1;
*/ private int mRightStickXAxis = -1;
private static void mapUnknownGamepad( private int mRightStickYAxis = -1;
float[] mappedButtons, float[] rawButtons, float[] mappedAxes, float[] rawAxes) { private boolean mUseHatAxes = false;
UnknownGamepadMappings(int[] axes) {
int hatAxesFound = 0;
for (int axis : axes) {
switch (axis) {
case MotionEvent.AXIS_LTRIGGER:
case MotionEvent.AXIS_BRAKE:
mLeftTriggerAxis = axis;
break;
case MotionEvent.AXIS_RTRIGGER:
case MotionEvent.AXIS_GAS:
case MotionEvent.AXIS_THROTTLE:
mRightTriggerAxis = axis;
break;
case MotionEvent.AXIS_RX:
case MotionEvent.AXIS_Z:
mRightStickXAxis = axis;
break;
case MotionEvent.AXIS_RY:
case MotionEvent.AXIS_RZ:
mRightStickYAxis = axis;
break;
case MotionEvent.AXIS_HAT_X:
hatAxesFound++;
break;
case MotionEvent.AXIS_HAT_Y:
hatAxesFound++;
break;
default:
break;
}
}
if (hatAxesFound == 2) {
mUseHatAxes = true;
}
}
@Override
public boolean isStandard() {
// These mappings should not be considered standard
return false;
}
@Override
public void mapToStandardGamepad(float[] mappedAxes, float[] mappedButtons,
float[] rawAxes, float[] rawButtons) {
// These are shared among all gamepads intended for use with Android
// that we tested so far.
mapCommonXYABButtons(mappedButtons, rawButtons); mapCommonXYABButtons(mappedButtons, rawButtons);
mapCommonTriggerButtons(mappedButtons, rawButtons); mapTriggerButtonsToTopShoulder(mappedButtons, rawButtons);
mapCommonThumbstickButtons(mappedButtons, rawButtons); mapCommonThumbstickButtons(mappedButtons, rawButtons);
mapCommonStartSelectMetaButtons(mappedButtons, rawButtons); mapCommonStartSelectMetaButtons(mappedButtons, rawButtons);
mapTriggerAxexToShoulderButtons(mappedButtons, rawAxes);
mapCommonDpadButtons(mappedButtons, rawButtons);
mapXYAxes(mappedAxes, rawAxes); mapXYAxes(mappedAxes, rawAxes);
mapRXAndRYAxesToRightStick(mappedAxes, rawAxes);
if (mLeftTriggerAxis != -1 && mRightTriggerAxis != -1) {
float lTrigger = rawAxes[mLeftTriggerAxis];
float rTrigger = rawAxes[mRightTriggerAxis];
mappedButtons[CanonicalButtonIndex.LEFT_TRIGGER] = lTrigger;
mappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER] = rTrigger;
} else {
// Devices without analog triggers use digital buttons
mapLowerTriggerButtonsToBottomShoulder(mappedButtons, rawButtons);
}
if (mRightStickXAxis != -1 && mRightStickYAxis != -1) {
float rX = rawAxes[mRightStickXAxis];
float rY = rawAxes[mRightStickYAxis];
mappedAxes[CanonicalAxisIndex.RIGHT_STICK_X] = rX;
mappedAxes[CanonicalAxisIndex.RIGHT_STICK_Y] = rY;
}
if (mUseHatAxes) {
mapHatAxisToDpadButtons(mappedButtons, rawAxes);
} else {
mapCommonDpadButtons(mappedButtons, rawButtons);
}
}
} }
} }
...@@ -62,8 +62,9 @@ public class GamepadMappingsTest { ...@@ -62,8 +62,9 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testShieldGamepadMappings() throws Exception { public void testShieldGamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, GamepadMappings mappings = GamepadMappings.getMappings(
GamepadMappings.NVIDIA_SHIELD_DEVICE_NAME_PREFIX); GamepadMappings.NVIDIA_SHIELD_DEVICE_NAME_PREFIX, null);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertShieldGamepadMappings(); assertShieldGamepadMappings();
} }
...@@ -71,8 +72,9 @@ public class GamepadMappingsTest { ...@@ -71,8 +72,9 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testXBox360GamepadMappings() throws Exception { public void testXBox360GamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, GamepadMappings mappings = GamepadMappings.getMappings(
GamepadMappings.MICROSOFT_XBOX_PAD_DEVICE_NAME); GamepadMappings.MICROSOFT_XBOX_PAD_DEVICE_NAME, null);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertShieldGamepadMappings(); assertShieldGamepadMappings();
} }
...@@ -80,8 +82,9 @@ public class GamepadMappingsTest { ...@@ -80,8 +82,9 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testPS3SixAxisGamepadMappings() throws Exception { public void testPS3SixAxisGamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, GamepadMappings mappings = GamepadMappings.getMappings(
GamepadMappings.PS3_SIXAXIS_DEVICE_NAME); GamepadMappings.PS3_SIXAXIS_DEVICE_NAME, null);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.PRIMARY], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.PRIMARY],
mRawButtons[KeyEvent.KEYCODE_BUTTON_X], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_BUTTON_X], ERROR_TOLERANCE);
...@@ -92,11 +95,11 @@ public class GamepadMappingsTest { ...@@ -92,11 +95,11 @@ public class GamepadMappingsTest {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.QUATERNARY], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.QUATERNARY],
mRawButtons[KeyEvent.KEYCODE_BUTTON_B], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_BUTTON_B], ERROR_TOLERANCE);
assertMappedCommonTriggerButtons(); assertMappedTriggerButtonsToTopShoulder();
assertMappedCommonThumbstickButtons(); assertMappedCommonThumbstickButtons();
assertMappedCommonDpadButtons(); assertMappedCommonDpadButtons();
assertMappedCommonStartSelectMetaButtons(); assertMappedCommonStartSelectMetaButtons();
assertMappedTriggerAxexToShoulderButtons(); assertMappedTriggerAxesToBottomShoulder();
assertMappedXYAxes(); assertMappedXYAxes();
assertMappedZAndRZAxesToRightStick(); assertMappedZAndRZAxesToRightStick();
...@@ -106,11 +109,12 @@ public class GamepadMappingsTest { ...@@ -106,11 +109,12 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testSamsungEIGP20GamepadMappings() throws Exception { public void testSamsungEIGP20GamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, GamepadMappings mappings = GamepadMappings.getMappings(
GamepadMappings.SAMSUNG_EI_GP20_DEVICE_NAME); GamepadMappings.SAMSUNG_EI_GP20_DEVICE_NAME, null);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons(); assertMappedCommonXYABButtons();
assertMappedCommonTriggerButtons(); assertMappedUpperTriggerButtonsToBottomShoulder();
assertMappedCommonThumbstickButtons(); assertMappedCommonThumbstickButtons();
assertMappedCommonStartSelectMetaButtons(); assertMappedCommonStartSelectMetaButtons();
assertMappedHatAxisToDpadButtons(); assertMappedHatAxisToDpadButtons();
...@@ -124,8 +128,9 @@ public class GamepadMappingsTest { ...@@ -124,8 +128,9 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testAmazonFireGamepadMappings() throws Exception { public void testAmazonFireGamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, GamepadMappings mappings = GamepadMappings.getMappings(
GamepadMappings.AMAZON_FIRE_DEVICE_NAME); GamepadMappings.AMAZON_FIRE_DEVICE_NAME, null);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons(); assertMappedCommonXYABButtons();
assertMappedPedalAxesToBottomShoulder(); assertMappedPedalAxesToBottomShoulder();
...@@ -141,22 +146,116 @@ public class GamepadMappingsTest { ...@@ -141,22 +146,116 @@ public class GamepadMappingsTest {
@Test @Test
@Feature({"Gamepad"}) @Feature({"Gamepad"})
public void testUnknownGamepadMappings() throws Exception { public void testUnknownXBox360GamepadMappings() throws Exception {
GamepadMappings.mapToStandardGamepad( int[] axes = new int[] {
mMappedAxes, mMappedButtons, mRawAxes, mRawButtons, ""); MotionEvent.AXIS_X,
MotionEvent.AXIS_Y,
MotionEvent.AXIS_Z,
MotionEvent.AXIS_RZ,
MotionEvent.AXIS_LTRIGGER,
MotionEvent.AXIS_RTRIGGER,
MotionEvent.AXIS_HAT_X,
MotionEvent.AXIS_HAT_Y
};
GamepadMappings mappings = GamepadMappings.getMappings("", axes);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons(); assertMappedCommonXYABButtons();
assertMappedCommonTriggerButtons(); assertMappedTriggerButtonsToTopShoulder();
assertMappedCommonThumbstickButtons(); assertMappedCommonThumbstickButtons();
assertMappedCommonStartSelectMetaButtons(); assertMappedCommonStartSelectMetaButtons();
assertMappedTriggerAxexToShoulderButtons(); assertMappedTriggerAxesToBottomShoulder();
assertMappedCommonDpadButtons(); assertMappedHatAxisToDpadButtons();
assertMappedXYAxes();
assertMappedZAndRZAxesToRightStick();
assertMapping();
}
@Test
@Feature({"Gamepad"})
public void testUnknownMogaProGamepadMappings() throws Exception {
int[] axes = new int[] {
MotionEvent.AXIS_X,
MotionEvent.AXIS_Y,
MotionEvent.AXIS_Z,
MotionEvent.AXIS_RZ,
MotionEvent.AXIS_BRAKE,
MotionEvent.AXIS_GAS,
MotionEvent.AXIS_HAT_X,
MotionEvent.AXIS_HAT_Y
};
GamepadMappings mappings = GamepadMappings.getMappings("", axes);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons();
assertMappedTriggerButtonsToTopShoulder();
assertMappedCommonThumbstickButtons();
assertMappedCommonStartSelectMetaButtons();
assertMappedPedalAxesToBottomShoulder();
assertMappedHatAxisToDpadButtons();
assertMappedXYAxes();
assertMappedZAndRZAxesToRightStick();
assertMapping();
}
@Test
@Feature({"Gamepad"})
public void testUnknownXiaomiGamepadMappings() throws Exception {
int[] axes = new int[] {
MotionEvent.AXIS_X,
MotionEvent.AXIS_Y,
MotionEvent.AXIS_RX,
MotionEvent.AXIS_RY,
MotionEvent.AXIS_BRAKE,
MotionEvent.AXIS_THROTTLE,
MotionEvent.AXIS_HAT_X,
MotionEvent.AXIS_HAT_Y
};
GamepadMappings mappings = GamepadMappings.getMappings("", axes);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons();
assertMappedTriggerButtonsToTopShoulder();
assertMappedCommonThumbstickButtons();
assertMappedCommonStartSelectMetaButtons();
assertMappedAltPedalAxesToBottomShoulder();
assertMappedHatAxisToDpadButtons();
assertMappedXYAxes(); assertMappedXYAxes();
assertMappedRXAndRYAxesToRightStick(); assertMappedRXAndRYAxesToRightStick();
assertMapping(); assertMapping();
} }
@Test
@Feature({"Gamepad"})
public void testUnknownGpdXdGamepadMappings() throws Exception {
int[] axes = new int[] {
MotionEvent.AXIS_X,
MotionEvent.AXIS_Y,
MotionEvent.AXIS_Z,
MotionEvent.AXIS_RZ
};
GamepadMappings mappings = GamepadMappings.getMappings("", axes);
mappings.mapToStandardGamepad(mMappedAxes, mMappedButtons, mRawAxes, mRawButtons);
assertMappedCommonXYABButtons();
assertMappedTriggerButtonsToTopShoulder();
assertMappedCommonThumbstickButtons();
assertMappedCommonStartSelectMetaButtons();
assertMappedLowerTriggerButtonsToBottomShoulder();
assertMappedCommonDpadButtons();
assertMappedXYAxes();
assertMappedZAndRZAxesToRightStick();
assertMapping();
}
/** /**
* Asserts that the current gamepad mapping being tested matches the shield mappings. * Asserts that the current gamepad mapping being tested matches the shield mappings.
*/ */
...@@ -199,13 +298,20 @@ public class GamepadMappingsTest { ...@@ -199,13 +298,20 @@ public class GamepadMappingsTest {
} }
} }
private void assertMappedCommonTriggerButtons() { private void assertMappedUpperTriggerButtonsToBottomShoulder() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER],
mRawButtons[KeyEvent.KEYCODE_BUTTON_L1], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_BUTTON_L1], ERROR_TOLERANCE);
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER],
mRawButtons[KeyEvent.KEYCODE_BUTTON_R1], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_BUTTON_R1], ERROR_TOLERANCE);
} }
private void assertMappedLowerTriggerButtonsToBottomShoulder() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER],
mRawButtons[KeyEvent.KEYCODE_BUTTON_L2], ERROR_TOLERANCE);
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER],
mRawButtons[KeyEvent.KEYCODE_BUTTON_R2], ERROR_TOLERANCE);
}
private void assertMappedCommonDpadButtons() { private void assertMappedCommonDpadButtons() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.DPAD_DOWN], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.DPAD_DOWN],
mRawButtons[KeyEvent.KEYCODE_DPAD_DOWN], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_DPAD_DOWN], ERROR_TOLERANCE);
...@@ -217,13 +323,6 @@ public class GamepadMappingsTest { ...@@ -217,13 +323,6 @@ public class GamepadMappingsTest {
mRawButtons[KeyEvent.KEYCODE_DPAD_RIGHT], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_DPAD_RIGHT], ERROR_TOLERANCE);
} }
private void assertMappedTriggerAxexToShoulderButtons() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_SHOULDER],
mRawAxes[MotionEvent.AXIS_LTRIGGER], ERROR_TOLERANCE);
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.RIGHT_SHOULDER],
mRawAxes[MotionEvent.AXIS_RTRIGGER], ERROR_TOLERANCE);
}
private void assertMappedTriggerButtonsToTopShoulder() { private void assertMappedTriggerButtonsToTopShoulder() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_SHOULDER], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_SHOULDER],
mRawButtons[KeyEvent.KEYCODE_BUTTON_L1], ERROR_TOLERANCE); mRawButtons[KeyEvent.KEYCODE_BUTTON_L1], ERROR_TOLERANCE);
...@@ -265,6 +364,13 @@ public class GamepadMappingsTest { ...@@ -265,6 +364,13 @@ public class GamepadMappingsTest {
mRawAxes[MotionEvent.AXIS_GAS], ERROR_TOLERANCE); mRawAxes[MotionEvent.AXIS_GAS], ERROR_TOLERANCE);
} }
private void assertMappedAltPedalAxesToBottomShoulder() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER],
mRawAxes[MotionEvent.AXIS_BRAKE], ERROR_TOLERANCE);
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.RIGHT_TRIGGER],
mRawAxes[MotionEvent.AXIS_THROTTLE], ERROR_TOLERANCE);
}
private void assertMappedTriggerAxesToBottomShoulder() { private void assertMappedTriggerAxesToBottomShoulder() {
Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER], Assert.assertEquals(mMappedButtons[CanonicalButtonIndex.LEFT_TRIGGER],
mRawAxes[MotionEvent.AXIS_LTRIGGER], ERROR_TOLERANCE); mRawAxes[MotionEvent.AXIS_LTRIGGER], ERROR_TOLERANCE);
......
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