summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml362
-rwxr-xr-xcore/java/android/view/InputDevice.java38
-rwxr-xr-xcore/java/android/view/KeyEvent.java497
-rw-r--r--core/java/android/view/MotionEvent.java653
-rw-r--r--core/java/android/view/ViewRoot.java13
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java5
-rw-r--r--core/jni/android_view_MotionEvent.cpp39
-rw-r--r--data/keyboards/Android.mk18
-rw-r--r--data/keyboards/Generic.kcm126
-rw-r--r--data/keyboards/Generic.kl14
-rw-r--r--data/keyboards/Vendor_046d_Product_c216.kl37
-rw-r--r--data/keyboards/Vendor_054c_Product_0268.kl76
-rw-r--r--data/keyboards/common.mk2
-rw-r--r--include/ui/Input.h42
-rw-r--r--include/ui/KeyLayoutMap.h12
-rw-r--r--include/ui/Keyboard.h12
-rwxr-xr-xinclude/ui/KeycodeLabels.h43
-rw-r--r--libs/ui/Input.cpp56
-rw-r--r--libs/ui/KeyLayoutMap.cpp70
-rw-r--r--libs/ui/Keyboard.cpp24
-rw-r--r--libs/ui/tests/InputEvent_test.cpp425
-rw-r--r--native/include/android/input.h30
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java13
-rw-r--r--services/input/EventHub.cpp168
-rw-r--r--services/input/EventHub.h12
-rw-r--r--services/input/InputReader.cpp359
-rw-r--r--services/input/InputReader.h164
-rw-r--r--services/input/tests/InputReader_test.cpp7
-rw-r--r--tools/validatekeymaps/Main.cpp21
29 files changed, 2453 insertions, 885 deletions
diff --git a/api/current.xml b/api/current.xml
index 6279d8d..019ca71 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -210656,6 +210656,17 @@
visibility="public"
>
</method>
+<method name="getMotionAxes"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getMotionRange"
return="android.view.InputDevice.MotionRange"
abstract="false"
@@ -212226,6 +212237,19 @@
visibility="public"
>
</method>
+<method name="isGamepadButton"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+</method>
<method name="isLongPress"
return="boolean"
abstract="false"
@@ -212338,6 +212362,32 @@
visibility="public"
>
</method>
+<method name="keyCodeFromString"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="symbolicName" type="java.lang.String">
+</parameter>
+</method>
+<method name="keyCodeToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+</method>
<method name="metaStateHasModifiers"
return="boolean"
abstract="false"
@@ -216602,6 +216652,32 @@
<parameter name="metaState" type="int">
</parameter>
</method>
+<method name="axisFromString"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="symbolicName" type="java.lang.String">
+</parameter>
+</method>
+<method name="axisToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="axis" type="int">
+</parameter>
+</method>
<method name="findPointerIndex"
return="int"
abstract="false"
@@ -217841,6 +217917,226 @@
visibility="public"
>
</field>
+<field name="AXIS_GENERIC_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="41"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="42"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="43"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="44"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="45"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="46"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="47"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="37"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="38"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="39"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GENERIC_9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="40"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_HAT_X"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_HAT_Y"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_HSCROLL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_LTRIGGER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_ORIENTATION"
type="int"
transient="false"
@@ -217863,6 +218159,50 @@
visibility="public"
>
</field>
+<field name="AXIS_RTRIGGER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="18"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_RX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_RY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_RZ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_SIZE"
type="int"
transient="false"
@@ -217918,6 +218258,17 @@
visibility="public"
>
</field>
+<field name="AXIS_VSCROLL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_X"
type="int"
transient="false"
@@ -217940,6 +218291,17 @@
visibility="public"
>
</field>
+<field name="AXIS_Z"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CREATOR"
type="android.os.Parcelable.Creator"
transient="false"
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 7abbce6..def1161 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -44,6 +44,7 @@ public final class InputDevice implements Parcelable {
private int mKeyboardType;
private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>();
+ private int[] mMotionAxes;
/**
* A mask for input source classes.
@@ -359,12 +360,31 @@ public final class InputDevice implements Parcelable {
*
* @see MotionEvent#AXIS_X
* @see MotionEvent#AXIS_Y
+ * @see #getSupportedAxes()
*/
public MotionRange getMotionRange(int axis) {
return mMotionRanges.get(axis);
}
- // Called by native code.
+ /**
+ * Gets the axis ids of all motion axes supported by this device.
+ * @return The axis ids of all motion axes supported by this device.
+ *
+ * @see #getMotionRange(int)
+ */
+ public int[] getMotionAxes() {
+ synchronized (this) {
+ if (mMotionAxes == null) {
+ final int count = mMotionRanges.size();
+ mMotionAxes = new int[count];
+ for (int i = 0; i < count; i++) {
+ mMotionAxes[i] = mMotionRanges.keyAt(i);
+ }
+ }
+ return mMotionAxes;
+ }
+ }
+
private void addMotionRange(int axis, float min, float max, float flat, float fuzz) {
mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz));
}
@@ -388,33 +408,35 @@ public final class InputDevice implements Parcelable {
}
/**
- * Gets the minimum value for the axis.
- * @return The (inclusive) minimum value.
+ * Gets the inclusive minimum value for the axis.
+ * @return The inclusive minimum value.
*/
public float getMin() {
return mMin;
}
/**
- * Gets the maximum value for the axis.
- * @return The (inclusive) maximum value.
+ * Gets the inclusive maximum value for the axis.
+ * @return The inclusive maximum value.
*/
public float getMax() {
return mMax;
}
/**
- * Gets the range of the axis (difference between maximum and minimum plus one).
+ * Gets the range of the axis (difference between maximum and minimum).
* @return The range of values.
*/
public float getRange() {
- return mMax - mMin + 1;
+ return mMax - mMin;
}
/**
* Gets the extent of the center flat position with respect to this axis.
+ * <p>
* For example, a flat value of 8 means that the center position is between -8 and +8.
* This value is mainly useful for calibrating self-centering devices.
+ * </p>
* @return The extent of the center flat position.
*/
public float getFlat() {
@@ -423,8 +445,10 @@ public final class InputDevice implements Parcelable {
/**
* Gets the error tolerance for input device measurements with respect to this axis.
+ * <p>
* For example, a value of 2 indicates that the measured value may be up to +/- 2 units
* away from the actual value due to noise and device sensitivity limitations.
+ * </p>
* @return The error tolerance.
*/
public float getFuzz() {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 3f6a04b..81d5a6e 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -21,6 +21,7 @@ import android.os.Parcelable;
import android.text.method.MetaKeyKeyListener;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.KeyCharacterMap;
import android.view.KeyCharacterMap.KeyData;
@@ -582,213 +583,214 @@ public class KeyEvent extends InputEvent implements Parcelable {
// those new codes. This is intended to maintain a consistent
// set of key code definitions across all Android devices.
- // Symbolic names of all keys indexed by keycode.
- // There should be exactly LAST_KEYCODE + 1 entries in this table.
- private static final String[] KEYCODE_SYMBOLIC_NAMES = new String[] {
- "KEYCODE_UNKNOWN",
- "KEYCODE_SOFT_LEFT",
- "KEYCODE_SOFT_RIGHT",
- "KEYCODE_HOME",
- "KEYCODE_BACK",
- "KEYCODE_CALL",
- "KEYCODE_ENDCALL",
- "KEYCODE_0",
- "KEYCODE_1",
- "KEYCODE_2",
- "KEYCODE_3",
- "KEYCODE_4",
- "KEYCODE_5",
- "KEYCODE_6",
- "KEYCODE_7",
- "KEYCODE_8",
- "KEYCODE_9",
- "KEYCODE_STAR",
- "KEYCODE_POUND",
- "KEYCODE_DPAD_UP",
- "KEYCODE_DPAD_DOWN",
- "KEYCODE_DPAD_LEFT",
- "KEYCODE_DPAD_RIGHT",
- "KEYCODE_DPAD_CENTER",
- "KEYCODE_VOLUME_UP",
- "KEYCODE_VOLUME_DOWN",
- "KEYCODE_POWER",
- "KEYCODE_CAMERA",
- "KEYCODE_CLEAR",
- "KEYCODE_A",
- "KEYCODE_B",
- "KEYCODE_C",
- "KEYCODE_D",
- "KEYCODE_E",
- "KEYCODE_F",
- "KEYCODE_G",
- "KEYCODE_H",
- "KEYCODE_I",
- "KEYCODE_J",
- "KEYCODE_K",
- "KEYCODE_L",
- "KEYCODE_M",
- "KEYCODE_N",
- "KEYCODE_O",
- "KEYCODE_P",
- "KEYCODE_Q",
- "KEYCODE_R",
- "KEYCODE_S",
- "KEYCODE_T",
- "KEYCODE_U",
- "KEYCODE_V",
- "KEYCODE_W",
- "KEYCODE_X",
- "KEYCODE_Y",
- "KEYCODE_Z",
- "KEYCODE_COMMA",
- "KEYCODE_PERIOD",
- "KEYCODE_ALT_LEFT",
- "KEYCODE_ALT_RIGHT",
- "KEYCODE_SHIFT_LEFT",
- "KEYCODE_SHIFT_RIGHT",
- "KEYCODE_TAB",
- "KEYCODE_SPACE",
- "KEYCODE_SYM",
- "KEYCODE_EXPLORER",
- "KEYCODE_ENVELOPE",
- "KEYCODE_ENTER",
- "KEYCODE_DEL",
- "KEYCODE_GRAVE",
- "KEYCODE_MINUS",
- "KEYCODE_EQUALS",
- "KEYCODE_LEFT_BRACKET",
- "KEYCODE_RIGHT_BRACKET",
- "KEYCODE_BACKSLASH",
- "KEYCODE_SEMICOLON",
- "KEYCODE_APOSTROPHE",
- "KEYCODE_SLASH",
- "KEYCODE_AT",
- "KEYCODE_NUM",
- "KEYCODE_HEADSETHOOK",
- "KEYCODE_FOCUS",
- "KEYCODE_PLUS",
- "KEYCODE_MENU",
- "KEYCODE_NOTIFICATION",
- "KEYCODE_SEARCH",
- "KEYCODE_MEDIA_PLAY_PAUSE",
- "KEYCODE_MEDIA_STOP",
- "KEYCODE_MEDIA_NEXT",
- "KEYCODE_MEDIA_PREVIOUS",
- "KEYCODE_MEDIA_REWIND",
- "KEYCODE_MEDIA_FAST_FORWARD",
- "KEYCODE_MUTE",
- "KEYCODE_PAGE_UP",
- "KEYCODE_PAGE_DOWN",
- "KEYCODE_PICTSYMBOLS",
- "KEYCODE_SWITCH_CHARSET",
- "KEYCODE_BUTTON_A",
- "KEYCODE_BUTTON_B",
- "KEYCODE_BUTTON_C",
- "KEYCODE_BUTTON_X",
- "KEYCODE_BUTTON_Y",
- "KEYCODE_BUTTON_Z",
- "KEYCODE_BUTTON_L1",
- "KEYCODE_BUTTON_R1",
- "KEYCODE_BUTTON_L2",
- "KEYCODE_BUTTON_R2",
- "KEYCODE_BUTTON_THUMBL",
- "KEYCODE_BUTTON_THUMBR",
- "KEYCODE_BUTTON_START",
- "KEYCODE_BUTTON_SELECT",
- "KEYCODE_BUTTON_MODE",
- "KEYCODE_ESCAPE",
- "KEYCODE_FORWARD_DEL",
- "KEYCODE_CTRL_LEFT",
- "KEYCODE_CTRL_RIGHT",
- "KEYCODE_CAPS_LOCK",
- "KEYCODE_SCROLL_LOCK",
- "KEYCODE_META_LEFT",
- "KEYCODE_META_RIGHT",
- "KEYCODE_FUNCTION",
- "KEYCODE_SYSRQ",
- "KEYCODE_BREAK",
- "KEYCODE_MOVE_HOME",
- "KEYCODE_MOVE_END",
- "KEYCODE_INSERT",
- "KEYCODE_FORWARD",
- "KEYCODE_MEDIA_PLAY",
- "KEYCODE_MEDIA_PAUSE",
- "KEYCODE_MEDIA_CLOSE",
- "KEYCODE_MEDIA_EJECT",
- "KEYCODE_MEDIA_RECORD",
- "KEYCODE_F1",
- "KEYCODE_F2",
- "KEYCODE_F3",
- "KEYCODE_F4",
- "KEYCODE_F5",
- "KEYCODE_F6",
- "KEYCODE_F7",
- "KEYCODE_F8",
- "KEYCODE_F9",
- "KEYCODE_F10",
- "KEYCODE_F11",
- "KEYCODE_F12",
- "KEYCODE_NUM_LOCK",
- "KEYCODE_NUMPAD_0",
- "KEYCODE_NUMPAD_1",
- "KEYCODE_NUMPAD_2",
- "KEYCODE_NUMPAD_3",
- "KEYCODE_NUMPAD_4",
- "KEYCODE_NUMPAD_5",
- "KEYCODE_NUMPAD_6",
- "KEYCODE_NUMPAD_7",
- "KEYCODE_NUMPAD_8",
- "KEYCODE_NUMPAD_9",
- "KEYCODE_NUMPAD_DIVIDE",
- "KEYCODE_NUMPAD_MULTIPLY",
- "KEYCODE_MUMPAD_SUBTRACT",
- "KEYCODE_NUMPAD_ADD",
- "KEYCODE_NUMPAD_DOT",
- "KEYCODE_NUMPAD_COMMA",
- "KEYCODE_NUMPAD_ENTER",
- "KEYCODE_NUMPAD_EQUALS",
- "KEYCODE_NUMPAD_LEFT_PAREN",
- "KEYCODE_NUMPAD_RIGHT_PAREN",
- "KEYCODE_VOLUME_MUTE",
- "KEYCODE_INFO",
- "KEYCODE_CHANNEL_UP",
- "KEYCODE_CHANNEL_DOWN",
- "KEYCODE_ZOOM_IN",
- "KEYCODE_ZOOM_OUT",
- "KEYCODE_TV",
- "KEYCODE_WINDOW",
- "KEYCODE_GUIDE",
- "KEYCODE_DVR",
- "KEYCODE_BOOKMARK",
- "KEYCODE_CAPTIONS",
- "KEYCODE_SETTINGS",
- "KEYCODE_TV_POWER",
- "KEYCODE_TV_INPUT",
- "KEYCODE_STB_INPUT",
- "KEYCODE_STB_POWER",
- "KEYCODE_AVR_POWER",
- "KEYCODE_AVR_INPUT",
- "KEYCODE_PROG_RED",
- "KEYCODE_PROG_GREEN",
- "KEYCODE_PROG_YELLOW",
- "KEYCODE_PROG_BLUE",
- "KEYCODE_APP_SWITCH",
- "KEYCODE_BUTTON_1",
- "KEYCODE_BUTTON_2",
- "KEYCODE_BUTTON_3",
- "KEYCODE_BUTTON_4",
- "KEYCODE_BUTTON_5",
- "KEYCODE_BUTTON_6",
- "KEYCODE_BUTTON_7",
- "KEYCODE_BUTTON_8",
- "KEYCODE_BUTTON_9",
- "KEYCODE_BUTTON_10",
- "KEYCODE_BUTTON_11",
- "KEYCODE_BUTTON_12",
- "KEYCODE_BUTTON_13",
- "KEYCODE_BUTTON_14",
- "KEYCODE_BUTTON_15",
- "KEYCODE_BUTTON_16",
+ // Symbolic names of all key codes.
+ private static final SparseArray<String> KEYCODE_SYMBOLIC_NAMES = new SparseArray<String>();
+ private static void populateKeycodeSymbolicNames() {
+ SparseArray<String> names = KEYCODE_SYMBOLIC_NAMES;
+ names.append(KEYCODE_UNKNOWN, "KEYCODE_UNKNOWN");
+ names.append(KEYCODE_SOFT_LEFT, "KEYCODE_SOFT_LEFT");
+ names.append(KEYCODE_SOFT_RIGHT, "KEYCODE_SOFT_RIGHT");
+ names.append(KEYCODE_HOME, "KEYCODE_HOME");
+ names.append(KEYCODE_BACK, "KEYCODE_BACK");
+ names.append(KEYCODE_CALL, "KEYCODE_CALL");
+ names.append(KEYCODE_ENDCALL, "KEYCODE_ENDCALL");
+ names.append(KEYCODE_0, "KEYCODE_0");
+ names.append(KEYCODE_1, "KEYCODE_1");
+ names.append(KEYCODE_2, "KEYCODE_2");
+ names.append(KEYCODE_3, "KEYCODE_3");
+ names.append(KEYCODE_4, "KEYCODE_4");
+ names.append(KEYCODE_5, "KEYCODE_5");
+ names.append(KEYCODE_6, "KEYCODE_6");
+ names.append(KEYCODE_7, "KEYCODE_7");
+ names.append(KEYCODE_8, "KEYCODE_8");
+ names.append(KEYCODE_9, "KEYCODE_9");
+ names.append(KEYCODE_STAR, "KEYCODE_STAR");
+ names.append(KEYCODE_POUND, "KEYCODE_POUND");
+ names.append(KEYCODE_DPAD_UP, "KEYCODE_DPAD_UP");
+ names.append(KEYCODE_DPAD_DOWN, "KEYCODE_DPAD_DOWN");
+ names.append(KEYCODE_DPAD_LEFT, "KEYCODE_DPAD_LEFT");
+ names.append(KEYCODE_DPAD_RIGHT, "KEYCODE_DPAD_RIGHT");
+ names.append(KEYCODE_DPAD_CENTER, "KEYCODE_DPAD_CENTER");
+ names.append(KEYCODE_VOLUME_UP, "KEYCODE_VOLUME_UP");
+ names.append(KEYCODE_VOLUME_DOWN, "KEYCODE_VOLUME_DOWN");
+ names.append(KEYCODE_POWER, "KEYCODE_POWER");
+ names.append(KEYCODE_CAMERA, "KEYCODE_CAMERA");
+ names.append(KEYCODE_CLEAR, "KEYCODE_CLEAR");
+ names.append(KEYCODE_A, "KEYCODE_A");
+ names.append(KEYCODE_B, "KEYCODE_B");
+ names.append(KEYCODE_C, "KEYCODE_C");
+ names.append(KEYCODE_D, "KEYCODE_D");
+ names.append(KEYCODE_E, "KEYCODE_E");
+ names.append(KEYCODE_F, "KEYCODE_F");
+ names.append(KEYCODE_G, "KEYCODE_G");
+ names.append(KEYCODE_H, "KEYCODE_H");
+ names.append(KEYCODE_I, "KEYCODE_I");
+ names.append(KEYCODE_J, "KEYCODE_J");
+ names.append(KEYCODE_K, "KEYCODE_K");
+ names.append(KEYCODE_L, "KEYCODE_L");
+ names.append(KEYCODE_M, "KEYCODE_M");
+ names.append(KEYCODE_N, "KEYCODE_N");
+ names.append(KEYCODE_O, "KEYCODE_O");
+ names.append(KEYCODE_P, "KEYCODE_P");
+ names.append(KEYCODE_Q, "KEYCODE_Q");
+ names.append(KEYCODE_R, "KEYCODE_R");
+ names.append(KEYCODE_S, "KEYCODE_S");
+ names.append(KEYCODE_T, "KEYCODE_T");
+ names.append(KEYCODE_U, "KEYCODE_U");
+ names.append(KEYCODE_V, "KEYCODE_V");
+ names.append(KEYCODE_W, "KEYCODE_W");
+ names.append(KEYCODE_X, "KEYCODE_X");
+ names.append(KEYCODE_Y, "KEYCODE_Y");
+ names.append(KEYCODE_Z, "KEYCODE_Z");
+ names.append(KEYCODE_COMMA, "KEYCODE_COMMA");
+ names.append(KEYCODE_PERIOD, "KEYCODE_PERIOD");
+ names.append(KEYCODE_ALT_LEFT, "KEYCODE_ALT_LEFT");
+ names.append(KEYCODE_ALT_RIGHT, "KEYCODE_ALT_RIGHT");
+ names.append(KEYCODE_SHIFT_LEFT, "KEYCODE_SHIFT_LEFT");
+ names.append(KEYCODE_SHIFT_RIGHT, "KEYCODE_SHIFT_RIGHT");
+ names.append(KEYCODE_TAB, "KEYCODE_TAB");
+ names.append(KEYCODE_SPACE, "KEYCODE_SPACE");
+ names.append(KEYCODE_SYM, "KEYCODE_SYM");
+ names.append(KEYCODE_EXPLORER, "KEYCODE_EXPLORER");
+ names.append(KEYCODE_ENVELOPE, "KEYCODE_ENVELOPE");
+ names.append(KEYCODE_ENTER, "KEYCODE_ENTER");
+ names.append(KEYCODE_DEL, "KEYCODE_DEL");
+ names.append(KEYCODE_GRAVE, "KEYCODE_GRAVE");
+ names.append(KEYCODE_MINUS, "KEYCODE_MINUS");
+ names.append(KEYCODE_EQUALS, "KEYCODE_EQUALS");
+ names.append(KEYCODE_LEFT_BRACKET, "KEYCODE_LEFT_BRACKET");
+ names.append(KEYCODE_RIGHT_BRACKET, "KEYCODE_RIGHT_BRACKET");
+ names.append(KEYCODE_BACKSLASH, "KEYCODE_BACKSLASH");
+ names.append(KEYCODE_SEMICOLON, "KEYCODE_SEMICOLON");
+ names.append(KEYCODE_APOSTROPHE, "KEYCODE_APOSTROPHE");
+ names.append(KEYCODE_SLASH, "KEYCODE_SLASH");
+ names.append(KEYCODE_AT, "KEYCODE_AT");
+ names.append(KEYCODE_NUM, "KEYCODE_NUM");
+ names.append(KEYCODE_HEADSETHOOK, "KEYCODE_HEADSETHOOK");
+ names.append(KEYCODE_FOCUS, "KEYCODE_FOCUS");
+ names.append(KEYCODE_PLUS, "KEYCODE_PLUS");
+ names.append(KEYCODE_MENU, "KEYCODE_MENU");
+ names.append(KEYCODE_NOTIFICATION, "KEYCODE_NOTIFICATION");
+ names.append(KEYCODE_SEARCH, "KEYCODE_SEARCH");
+ names.append(KEYCODE_MEDIA_PLAY_PAUSE, "KEYCODE_MEDIA_PLAY_PAUSE");
+ names.append(KEYCODE_MEDIA_STOP, "KEYCODE_MEDIA_STOP");
+ names.append(KEYCODE_MEDIA_NEXT, "KEYCODE_MEDIA_NEXT");
+ names.append(KEYCODE_MEDIA_PREVIOUS, "KEYCODE_MEDIA_PREVIOUS");
+ names.append(KEYCODE_MEDIA_REWIND, "KEYCODE_MEDIA_REWIND");
+ names.append(KEYCODE_MEDIA_FAST_FORWARD, "KEYCODE_MEDIA_FAST_FORWARD");
+ names.append(KEYCODE_MUTE, "KEYCODE_MUTE");
+ names.append(KEYCODE_PAGE_UP, "KEYCODE_PAGE_UP");
+ names.append(KEYCODE_PAGE_DOWN, "KEYCODE_PAGE_DOWN");
+ names.append(KEYCODE_PICTSYMBOLS, "KEYCODE_PICTSYMBOLS");
+ names.append(KEYCODE_SWITCH_CHARSET, "KEYCODE_SWITCH_CHARSET");
+ names.append(KEYCODE_BUTTON_A, "KEYCODE_BUTTON_A");
+ names.append(KEYCODE_BUTTON_B, "KEYCODE_BUTTON_B");
+ names.append(KEYCODE_BUTTON_C, "KEYCODE_BUTTON_C");
+ names.append(KEYCODE_BUTTON_X, "KEYCODE_BUTTON_X");
+ names.append(KEYCODE_BUTTON_Y, "KEYCODE_BUTTON_Y");
+ names.append(KEYCODE_BUTTON_Z, "KEYCODE_BUTTON_Z");
+ names.append(KEYCODE_BUTTON_L1, "KEYCODE_BUTTON_L1");
+ names.append(KEYCODE_BUTTON_R1, "KEYCODE_BUTTON_R1");
+ names.append(KEYCODE_BUTTON_L2, "KEYCODE_BUTTON_L2");
+ names.append(KEYCODE_BUTTON_R2, "KEYCODE_BUTTON_R2");
+ names.append(KEYCODE_BUTTON_THUMBL, "KEYCODE_BUTTON_THUMBL");
+ names.append(KEYCODE_BUTTON_THUMBR, "KEYCODE_BUTTON_THUMBR");
+ names.append(KEYCODE_BUTTON_START, "KEYCODE_BUTTON_START");
+ names.append(KEYCODE_BUTTON_SELECT, "KEYCODE_BUTTON_SELECT");
+ names.append(KEYCODE_BUTTON_MODE, "KEYCODE_BUTTON_MODE");
+ names.append(KEYCODE_ESCAPE, "KEYCODE_ESCAPE");
+ names.append(KEYCODE_FORWARD_DEL, "KEYCODE_FORWARD_DEL");
+ names.append(KEYCODE_CTRL_LEFT, "KEYCODE_CTRL_LEFT");
+ names.append(KEYCODE_CTRL_RIGHT, "KEYCODE_CTRL_RIGHT");
+ names.append(KEYCODE_CAPS_LOCK, "KEYCODE_CAPS_LOCK");
+ names.append(KEYCODE_SCROLL_LOCK, "KEYCODE_SCROLL_LOCK");
+ names.append(KEYCODE_META_LEFT, "KEYCODE_META_LEFT");
+ names.append(KEYCODE_META_RIGHT, "KEYCODE_META_RIGHT");
+ names.append(KEYCODE_FUNCTION, "KEYCODE_FUNCTION");
+ names.append(KEYCODE_SYSRQ, "KEYCODE_SYSRQ");
+ names.append(KEYCODE_BREAK, "KEYCODE_BREAK");
+ names.append(KEYCODE_MOVE_HOME, "KEYCODE_MOVE_HOME");
+ names.append(KEYCODE_MOVE_END, "KEYCODE_MOVE_END");
+ names.append(KEYCODE_INSERT, "KEYCODE_INSERT");
+ names.append(KEYCODE_FORWARD, "KEYCODE_FORWARD");
+ names.append(KEYCODE_MEDIA_PLAY, "KEYCODE_MEDIA_PLAY");
+ names.append(KEYCODE_MEDIA_PAUSE, "KEYCODE_MEDIA_PAUSE");
+ names.append(KEYCODE_MEDIA_CLOSE, "KEYCODE_MEDIA_CLOSE");
+ names.append(KEYCODE_MEDIA_EJECT, "KEYCODE_MEDIA_EJECT");
+ names.append(KEYCODE_MEDIA_RECORD, "KEYCODE_MEDIA_RECORD");
+ names.append(KEYCODE_F1, "KEYCODE_F1");
+ names.append(KEYCODE_F2, "KEYCODE_F2");
+ names.append(KEYCODE_F3, "KEYCODE_F3");
+ names.append(KEYCODE_F4, "KEYCODE_F4");
+ names.append(KEYCODE_F5, "KEYCODE_F5");
+ names.append(KEYCODE_F6, "KEYCODE_F6");
+ names.append(KEYCODE_F7, "KEYCODE_F7");
+ names.append(KEYCODE_F8, "KEYCODE_F8");
+ names.append(KEYCODE_F9, "KEYCODE_F9");
+ names.append(KEYCODE_F10, "KEYCODE_F10");
+ names.append(KEYCODE_F11, "KEYCODE_F11");
+ names.append(KEYCODE_F12, "KEYCODE_F12");
+ names.append(KEYCODE_NUM_LOCK, "KEYCODE_NUM_LOCK");
+ names.append(KEYCODE_NUMPAD_0, "KEYCODE_NUMPAD_0");
+ names.append(KEYCODE_NUMPAD_1, "KEYCODE_NUMPAD_1");
+ names.append(KEYCODE_NUMPAD_2, "KEYCODE_NUMPAD_2");
+ names.append(KEYCODE_NUMPAD_3, "KEYCODE_NUMPAD_3");
+ names.append(KEYCODE_NUMPAD_4, "KEYCODE_NUMPAD_4");
+ names.append(KEYCODE_NUMPAD_5, "KEYCODE_NUMPAD_5");
+ names.append(KEYCODE_NUMPAD_6, "KEYCODE_NUMPAD_6");
+ names.append(KEYCODE_NUMPAD_7, "KEYCODE_NUMPAD_7");
+ names.append(KEYCODE_NUMPAD_8, "KEYCODE_NUMPAD_8");
+ names.append(KEYCODE_NUMPAD_9, "KEYCODE_NUMPAD_9");
+ names.append(KEYCODE_NUMPAD_DIVIDE, "KEYCODE_NUMPAD_DIVIDE");
+ names.append(KEYCODE_NUMPAD_MULTIPLY, "KEYCODE_NUMPAD_MULTIPLY");
+ names.append(KEYCODE_NUMPAD_SUBTRACT, "KEYCODE_NUMPAD_SUBTRACT");
+ names.append(KEYCODE_NUMPAD_ADD, "KEYCODE_NUMPAD_ADD");
+ names.append(KEYCODE_NUMPAD_DOT, "KEYCODE_NUMPAD_DOT");
+ names.append(KEYCODE_NUMPAD_COMMA, "KEYCODE_NUMPAD_COMMA");
+ names.append(KEYCODE_NUMPAD_ENTER, "KEYCODE_NUMPAD_ENTER");
+ names.append(KEYCODE_NUMPAD_EQUALS, "KEYCODE_NUMPAD_EQUALS");
+ names.append(KEYCODE_NUMPAD_LEFT_PAREN, "KEYCODE_NUMPAD_LEFT_PAREN");
+ names.append(KEYCODE_NUMPAD_RIGHT_PAREN, "KEYCODE_NUMPAD_RIGHT_PAREN");
+ names.append(KEYCODE_VOLUME_MUTE, "KEYCODE_VOLUME_MUTE");
+ names.append(KEYCODE_INFO, "KEYCODE_INFO");
+ names.append(KEYCODE_CHANNEL_UP, "KEYCODE_CHANNEL_UP");
+ names.append(KEYCODE_CHANNEL_DOWN, "KEYCODE_CHANNEL_DOWN");
+ names.append(KEYCODE_ZOOM_IN, "KEYCODE_ZOOM_IN");
+ names.append(KEYCODE_ZOOM_OUT, "KEYCODE_ZOOM_OUT");
+ names.append(KEYCODE_TV, "KEYCODE_TV");
+ names.append(KEYCODE_WINDOW, "KEYCODE_WINDOW");
+ names.append(KEYCODE_GUIDE, "KEYCODE_GUIDE");
+ names.append(KEYCODE_DVR, "KEYCODE_DVR");
+ names.append(KEYCODE_BOOKMARK, "KEYCODE_BOOKMARK");
+ names.append(KEYCODE_CAPTIONS, "KEYCODE_CAPTIONS");
+ names.append(KEYCODE_SETTINGS, "KEYCODE_SETTINGS");
+ names.append(KEYCODE_TV_POWER, "KEYCODE_TV_POWER");
+ names.append(KEYCODE_TV_INPUT, "KEYCODE_TV_INPUT");
+ names.append(KEYCODE_STB_INPUT, "KEYCODE_STB_INPUT");
+ names.append(KEYCODE_STB_POWER, "KEYCODE_STB_POWER");
+ names.append(KEYCODE_AVR_POWER, "KEYCODE_AVR_POWER");
+ names.append(KEYCODE_AVR_INPUT, "KEYCODE_AVR_INPUT");
+ names.append(KEYCODE_PROG_RED, "KEYCODE_PROG_RED");
+ names.append(KEYCODE_PROG_GREEN, "KEYCODE_PROG_GREEN");
+ names.append(KEYCODE_PROG_YELLOW, "KEYCODE_PROG_YELLOW");
+ names.append(KEYCODE_PROG_BLUE, "KEYCODE_PROG_BLUE");
+ names.append(KEYCODE_APP_SWITCH, "KEYCODE_APP_SWITCH");
+ names.append(KEYCODE_BUTTON_1, "KEYCODE_BUTTON_1");
+ names.append(KEYCODE_BUTTON_2, "KEYCODE_BUTTON_2");
+ names.append(KEYCODE_BUTTON_3, "KEYCODE_BUTTON_3");
+ names.append(KEYCODE_BUTTON_4, "KEYCODE_BUTTON_4");
+ names.append(KEYCODE_BUTTON_5, "KEYCODE_BUTTON_5");
+ names.append(KEYCODE_BUTTON_6, "KEYCODE_BUTTON_6");
+ names.append(KEYCODE_BUTTON_7, "KEYCODE_BUTTON_7");
+ names.append(KEYCODE_BUTTON_8, "KEYCODE_BUTTON_8");
+ names.append(KEYCODE_BUTTON_9, "KEYCODE_BUTTON_9");
+ names.append(KEYCODE_BUTTON_10, "KEYCODE_BUTTON_10");
+ names.append(KEYCODE_BUTTON_11, "KEYCODE_BUTTON_11");
+ names.append(KEYCODE_BUTTON_12, "KEYCODE_BUTTON_12");
+ names.append(KEYCODE_BUTTON_13, "KEYCODE_BUTTON_13");
+ names.append(KEYCODE_BUTTON_14, "KEYCODE_BUTTON_14");
+ names.append(KEYCODE_BUTTON_15, "KEYCODE_BUTTON_15");
+ names.append(KEYCODE_BUTTON_16, "KEYCODE_BUTTON_16");
};
// Symbolic names of all metakeys in bit order from least significant to most significant.
@@ -1250,14 +1252,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
}
static {
- if (META_SYMBOLIC_NAMES.length != 32) {
- throw new IllegalStateException(
- "META_SYMBOLIC_NAMES array should contain exactly 32 entries.");
- }
- if (KEYCODE_SYMBOLIC_NAMES.length != LAST_KEYCODE + 1) {
- throw new IllegalStateException(
- "KEYCODE_SYMBOLIC_NAMES array is out of sync with the keycode constants.");
- }
+ populateKeycodeSymbolicNames();
}
private KeyEvent() {
@@ -1653,6 +1648,49 @@ public class KeyEvent extends InputEvent implements Parcelable {
return native_hasDefaultAction(mKeyCode);
}
+ /**
+ * Returns true if the specified keycode is a gamepad button.
+ * @return True if the keycode is a gamepad button, such as {@link #KEYCODE_BUTTON_A}.
+ */
+ public static final boolean isGamepadButton(int keyCode) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BUTTON_A:
+ case KeyEvent.KEYCODE_BUTTON_B:
+ case KeyEvent.KEYCODE_BUTTON_C:
+ case KeyEvent.KEYCODE_BUTTON_X:
+ case KeyEvent.KEYCODE_BUTTON_Y:
+ case KeyEvent.KEYCODE_BUTTON_Z:
+ case KeyEvent.KEYCODE_BUTTON_L1:
+ case KeyEvent.KEYCODE_BUTTON_R1:
+ case KeyEvent.KEYCODE_BUTTON_L2:
+ case KeyEvent.KEYCODE_BUTTON_R2:
+ case KeyEvent.KEYCODE_BUTTON_THUMBL:
+ case KeyEvent.KEYCODE_BUTTON_THUMBR:
+ case KeyEvent.KEYCODE_BUTTON_START:
+ case KeyEvent.KEYCODE_BUTTON_SELECT:
+ case KeyEvent.KEYCODE_BUTTON_MODE:
+ case KeyEvent.KEYCODE_BUTTON_1:
+ case KeyEvent.KEYCODE_BUTTON_2:
+ case KeyEvent.KEYCODE_BUTTON_3:
+ case KeyEvent.KEYCODE_BUTTON_4:
+ case KeyEvent.KEYCODE_BUTTON_5:
+ case KeyEvent.KEYCODE_BUTTON_6:
+ case KeyEvent.KEYCODE_BUTTON_7:
+ case KeyEvent.KEYCODE_BUTTON_8:
+ case KeyEvent.KEYCODE_BUTTON_9:
+ case KeyEvent.KEYCODE_BUTTON_10:
+ case KeyEvent.KEYCODE_BUTTON_11:
+ case KeyEvent.KEYCODE_BUTTON_12:
+ case KeyEvent.KEYCODE_BUTTON_13:
+ case KeyEvent.KEYCODE_BUTTON_14:
+ case KeyEvent.KEYCODE_BUTTON_15:
+ case KeyEvent.KEYCODE_BUTTON_16:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/** {@inheritDoc} */
@Override
public final int getDeviceId() {
@@ -2554,7 +2592,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
/**
* Returns a string that represents the symbolic name of the specified action
- * such as "ACTION_DOWN", or "35" (if unknown).
+ * such as "ACTION_DOWN", or an equivalent numeric constant such as "35" if unknown.
*
* @param action The action.
* @return The symbolic name of the specified action.
@@ -2575,52 +2613,51 @@ public class KeyEvent extends InputEvent implements Parcelable {
/**
* Returns a string that represents the symbolic name of the specified keycode
- * such as "KEYCODE_A", "KEYCODE_DPAD_UP", or "1001" (if unknown).
+ * such as "KEYCODE_A", "KEYCODE_DPAD_UP", or an equivalent numeric constant
+ * such as "1001" if unknown.
*
* @param keyCode The key code.
* @return The symbolic name of the specified keycode.
*
* @see KeyCharacterMap#getDisplayLabel
- * @hide
*/
public static String keyCodeToString(int keyCode) {
- if (keyCode >= 0 && keyCode < KEYCODE_SYMBOLIC_NAMES.length) {
- return KEYCODE_SYMBOLIC_NAMES[keyCode];
- }
- return Integer.toString(keyCode);
+ String symbolicName = KEYCODE_SYMBOLIC_NAMES.get(keyCode);
+ return symbolicName != null ? symbolicName : Integer.toString(keyCode);
}
/**
- * Gets a keycode by its symbolic name such as "KEYCODE_A" or "1001" (if unknown).
+ * Gets a keycode by its symbolic name such as "KEYCODE_A" or an equivalent
+ * numeric constant such as "1001".
*
* @param symbolicName The symbolic name of the keycode.
- * @return The keycode or -1 if not found.
+ * @return The keycode or {@link #KEYCODE_UNKNOWN} if not found.
* @see #keycodeToString
- * @hide
*/
public static int keyCodeFromString(String symbolicName) {
if (symbolicName == null) {
throw new IllegalArgumentException("symbolicName must not be null");
}
- final int count = KEYCODE_SYMBOLIC_NAMES.length;
+ final int count = KEYCODE_SYMBOLIC_NAMES.size();
for (int i = 0; i < count; i++) {
- if (symbolicName.equals(KEYCODE_SYMBOLIC_NAMES[i])) {
+ if (symbolicName.equals(KEYCODE_SYMBOLIC_NAMES.valueAt(i))) {
return i;
}
}
try {
- return Integer.parseInt(symbolicName,10);
+ return Integer.parseInt(symbolicName, 10);
} catch (NumberFormatException ex) {
- return -1;
+ return KEYCODE_UNKNOWN;
}
}
/**
* Returns a string that represents the symbolic name of the specified combined meta
* key modifier state flags such as "0", "META_SHIFT_ON",
- * "META_ALT_ON|META_SHIFT_ON" or "0x10000000" (if unknown).
+ * "META_ALT_ON|META_SHIFT_ON" or an equivalent numeric constant such as "0x10000000"
+ * if unknown.
*
* @param metaState The meta state.
* @return The symbolic name of the specified combined meta state flags.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 6673be2..a1326d2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -20,6 +20,7 @@ import android.graphics.Matrix;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
+import android.util.SparseArray;
/**
* Object used to report movement (mouse, pen, finger, trackball) events. This
@@ -263,10 +264,22 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the X axis of a motion event.
- *
- * The interpretation of the X axis varies by input source.
- * It may represent the X position of the center of the touch contact area,
- * a relative horizontal displacement of a trackball or joystick, or something else.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the absolute X screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * <li>For a touch pad, reports the absolute X surface position of the center of the touch
+ * contact area. The units are device-specific because the touch pad is not necessarily
+ * associated with a display. Use {@link InputDevice#getMotionRange(int)} to query
+ * the effective range of values.
+ * <li>For a mouse, reports the absolute X screen position of the mouse pointer.
+ * The units are display pixels.
+ * <li>For a trackball, reports the relative horizontal displacement of the trackball.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * <li>For a joystick, reports the absolute X position of the joystick.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * </ul>
+ * </p>
*
* @see #getX(int)
* @see #getHistoricalX(int, int)
@@ -277,10 +290,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the Y axis of a motion event.
- *
- * The interpretation of the Y axis varies by input source.
- * It may represent the Y position of the center of the touch contact area,
- * a relative vertical displacement of a trackball or joystick, or something else.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the absolute Y screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * <li>For a touch pad, reports the absolute Y surface position of the center of the touch
+ * contact area. The units are device-dependent; use {@link InputDevice#getMotionRange(int)}
+ * to query the effective range of values.
+ * <li>For a mouse, reports the absolute Y screen position of the mouse pointer.
+ * The units are display pixels.
+ * <li>For a trackball, reports the relative vertical displacement of the trackball.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * <li>For a joystick, reports the absolute Y position of the joystick.
+ * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+ * </ul>
+ * </p>
*
* @see #getY(int)
* @see #getHistoricalY(int, int)
@@ -291,12 +315,18 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the Pressure axis of a motion event.
- *
- * The pressure axis specifies a normalized value that describes the approximate
- * pressure applied to the device by a finger or other tool.
- * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
- * although values higher than 1 may be generated depending on the calibration of
- * the input device.
+ * <p>
+ * <ul>
+ * <li>For a touch screen or touch pad, reports the approximate pressure applied to the device
+ * by a finger or other tool. The value is normalized to a range from
+ * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+ * may be generated depending on the calibration of the input device.
+ * <li>For a trackball, the value is set to 1 if the trackball button is pressed
+ * or 0 otherwise.
+ * <li>For a mouse, the value is set to 1 if the primary mouse button is pressed
+ * or 0 otherwise.
+ * </ul>
+ * </p>
*
* @see #getPressure(int)
* @see #getHistoricalPressure(int, int)
@@ -307,17 +337,16 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the Size axis of a motion event.
- *
- * The size axis specifies a normalized value that describes the approximate size
- * of the pointer touch area in relation to the maximum detectable size for the device.
- * It represents some approximation of the area of the screen being
- * pressed; the actual value in pixels corresponding to the
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events.
- *
- * To obtain calibrated size information in terms of pixels, use
- * {@link #AXIS_TOUCH_MAJOR} or {@link #AXIS_TOOL_MAJOR} instead.
+ * <p>
+ * <ul>
+ * <li>For a touch screen or touch pad, reports the approximate size of the contact area in
+ * relation to the maximum detectable size for the device. The value is normalized
+ * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+ * although it is not a linear scale. This value is of very limited use.
+ * To obtain calibrated size information, use
+ * {@link #AXIS_TOUCH_MAJOR} or {@link #AXIS_TOOL_MAJOR}.
+ * </ul>
+ * </p>
*
* @see #getSize(int)
* @see #getHistoricalSize(int, int)
@@ -328,11 +357,17 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the TouchMajor axis of a motion event.
- *
- * The touch major axis specifies the length of the major axis of an ellipse that
- * describes the touch area at the point of contact.
- * If the device is a touch screen, the length is reported in pixels, otherwise it is
- * reported in device-specific units.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * <li>For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent; use {@link InputDevice#getMotionRange(int)}
+ * to query the effective range of values.
+ * </ul>
+ * </p>
*
* @see #getTouchMajor(int)
* @see #getHistoricalTouchMajor(int, int)
@@ -343,11 +378,19 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the TouchMinor axis of a motion event.
- *
- * The touch major axis specifies the length of the minor axis of an ellipse that
- * describes the touch area at the point of contact.
- * If the device is a touch screen, the length is reported in pixels, otherwise it is
- * reported in device-specific units.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * <li>For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent; use {@link InputDevice#getMotionRange(int)}
+ * to query the effective range of values.
+ * </ul>
+ * </p><p>
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ * </p>
*
* @see #getTouchMinor(int)
* @see #getHistoricalTouchMinor(int, int)
@@ -358,13 +401,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the ToolMajor axis of a motion event.
- *
- * The tool major axis specifies the length of the major axis of an ellipse that
- * describes the size of the approaching tool.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact.
- * If the device is a touch screen, the length is reported in pixels, otherwise it is
- * reported in device-specific units.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * <li>For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent; use {@link InputDevice#getMotionRange(int)}
+ * to query the effective range of values.
+ * </ul>
+ * </p><p>
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ * </p><p>
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ * </p>
*
* @see #getToolMajor(int)
* @see #getHistoricalToolMajor(int, int)
@@ -375,13 +426,21 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the ToolMinor axis of a motion event.
- *
- * The tool minor axis specifies the length of the major axis of an ellipse that
- * describes the size of the approaching tool.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact.
- * If the device is a touch screen, the length is reported in pixels, otherwise it is
- * reported in device-specific units.
+ * <p>
+ * <ul>
+ * <li>For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * <li>For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent; use {@link InputDevice#getMotionRange(int)}
+ * to query the effective range of values.
+ * </ul>
+ * </p><p>
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ * </p><p>
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ * </p>
*
* @see #getToolMinor(int)
* @see #getHistoricalToolMinor(int, int)
@@ -392,15 +451,18 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Constant used to identify the Orientation axis of a motion event.
- *
- * The orientation axis specifies the orientation of the touch area and tool area in
- * radians clockwise from vertical relative to the vertical plane of the device.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * <p>
+ * <ul>
+ * <li>For a touch screen or touch pad, reports the orientation of the finger
+ * or tool in radians relative to the vertical plane of the device.
+ * An angle of 0 radians indicates that the major axis of contact is oriented
* upwards, is perfectly circular or is of unknown orientation. A positive angle
* indicates that the major axis of contact is oriented to the right. A negative angle
* indicates that the major axis of contact is oriented to the left.
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
* (finger pointing fully right).
+ * </ul>
+ * </p>
*
* @see #getOrientation(int)
* @see #getHistoricalOrientation(int, int)
@@ -409,6 +471,399 @@ public final class MotionEvent extends InputEvent implements Parcelable {
*/
public static final int AXIS_ORIENTATION = 8;
+ /**
+ * Constant used to identify the Vertical Scroll axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a mouse, reports the relative movement of vertical scroll wheel.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * </ul>
+ * </p><p>
+ * This axis should be used to scroll views vertically.
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_VSCROLL = 9;
+
+ /**
+ * Constant used to identify the Horizontal Scroll axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a mouse, reports the relative movement of horizontal scroll wheel.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * </ul>
+ * </p><p>
+ * This axis should be used to scroll views horizontally.
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_HSCROLL = 10;
+
+ /**
+ * Constant used to identify the Z axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute Z position of the joystick.
+ * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+ * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute X position of the second joystick instead.</em>
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_Z = 11;
+
+ /**
+ * Constant used to identify the X Rotation axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute rotation angle about the X axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_RX = 12;
+
+ /**
+ * Constant used to identify the Y Rotation axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute rotation angle about the Y axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_RY = 13;
+
+ /**
+ * Constant used to identify the Z Rotation axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute rotation angle about the Z axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute Y position of the second joystick instead.</em>
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_RZ = 14;
+
+ /**
+ * Constant used to identify the Hat X axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute X position of the directional hat control.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_HAT_X = 15;
+
+ /**
+ * Constant used to identify the Hat Y axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute Y position of the directional hat control.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_HAT_Y = 16;
+
+ /**
+ * Constant used to identify the Left Trigger axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the left trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_LTRIGGER = 17;
+
+ /**
+ * Constant used to identify the Right Trigger axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the right trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_RTRIGGER = 18;
+
+ /**
+ * Constant used to identify the Generic 1 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_1 = 32;
+
+ /**
+ * Constant used to identify the Generic 2 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_2 = 33;
+
+ /**
+ * Constant used to identify the Generic 3 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_3 = 34;
+
+ /**
+ * Constant used to identify the Generic 4 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_4 = 35;
+
+ /**
+ * Constant used to identify the Generic 5 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_5 = 36;
+
+ /**
+ * Constant used to identify the Generic 6 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_6 = 37;
+
+ /**
+ * Constant used to identify the Generic 7 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_7 = 38;
+
+ /**
+ * Constant used to identify the Generic 8 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_8 = 39;
+
+ /**
+ * Constant used to identify the Generic 9 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_9 = 40;
+
+ /**
+ * Constant used to identify the Generic 10 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_10 = 41;
+
+ /**
+ * Constant used to identify the Generic 11 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_11 = 42;
+
+ /**
+ * Constant used to identify the Generic 12 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_12 = 43;
+
+ /**
+ * Constant used to identify the Generic 13 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_13 = 44;
+
+ /**
+ * Constant used to identify the Generic 14 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_14 = 45;
+
+ /**
+ * Constant used to identify the Generic 15 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_15 = 46;
+
+ /**
+ * Constant used to identify the Generic 16 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GENERIC_16 = 47;
+
+ // NOTE: If you add a new axis here you must also add it to:
+ // native/include/android/input.h
+ // frameworks/base/include/ui/KeycodeLabels.h
+
+ // Symbolic names of all axes.
+ private static final SparseArray<String> AXIS_SYMBOLIC_NAMES = new SparseArray<String>();
+ private static void populateAxisSymbolicNames() {
+ SparseArray<String> names = AXIS_SYMBOLIC_NAMES;
+ names.append(AXIS_X, "AXIS_X");
+ names.append(AXIS_Y, "AXIS_Y");
+ names.append(AXIS_PRESSURE, "AXIS_PRESSURE");
+ names.append(AXIS_SIZE, "AXIS_SIZE");
+ names.append(AXIS_TOUCH_MAJOR, "AXIS_TOUCH_MAJOR");
+ names.append(AXIS_TOUCH_MINOR, "AXIS_TOUCH_MINOR");
+ names.append(AXIS_TOOL_MAJOR, "AXIS_TOOL_MAJOR");
+ names.append(AXIS_TOOL_MINOR, "AXIS_TOOL_MINOR");
+ names.append(AXIS_ORIENTATION, "AXIS_ORIENTATION");
+ names.append(AXIS_VSCROLL, "AXIS_VSCROLL");
+ names.append(AXIS_HSCROLL, "AXIS_HSCROLL");
+ names.append(AXIS_Z, "AXIS_Z");
+ names.append(AXIS_RX, "AXIS_RX");
+ names.append(AXIS_RY, "AXIS_RY");
+ names.append(AXIS_RZ, "AXIS_RZ");
+ names.append(AXIS_HAT_X, "AXIS_HAT_X");
+ names.append(AXIS_HAT_Y, "AXIS_HAT_Y");
+ names.append(AXIS_LTRIGGER, "AXIS_LTRIGGER");
+ names.append(AXIS_RTRIGGER, "AXIS_RTRIGGER");
+ names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1");
+ names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2");
+ names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3");
+ names.append(AXIS_GENERIC_4, "AXIS_GENERIC_4");
+ names.append(AXIS_GENERIC_5, "AXIS_GENERIC_5");
+ names.append(AXIS_GENERIC_6, "AXIS_GENERIC_6");
+ names.append(AXIS_GENERIC_7, "AXIS_GENERIC_7");
+ names.append(AXIS_GENERIC_8, "AXIS_GENERIC_8");
+ names.append(AXIS_GENERIC_9, "AXIS_GENERIC_9");
+ names.append(AXIS_GENERIC_10, "AXIS_GENERIC_10");
+ names.append(AXIS_GENERIC_11, "AXIS_GENERIC_11");
+ names.append(AXIS_GENERIC_12, "AXIS_GENERIC_12");
+ names.append(AXIS_GENERIC_13, "AXIS_GENERIC_13");
+ names.append(AXIS_GENERIC_14, "AXIS_GENERIC_14");
+ names.append(AXIS_GENERIC_15, "AXIS_GENERIC_15");
+ names.append(AXIS_GENERIC_16, "AXIS_GENERIC_16");
+ }
+
+ static {
+ populateAxisSymbolicNames();
+ }
+
// Private value for history pos that obtains the current sample.
private static final int HISTORY_CURRENT = -0x80000000;
@@ -1081,7 +1536,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* Returns the orientation of the touch area and tool area in radians clockwise from vertical
* for the given pointer <em>index</em> (use {@link #getPointerId(int)} to find the pointer
* identifier for this index).
- * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * An angle of 0 radians indicates that the major axis of contact is oriented
* upwards, is perfectly circular or is of unknown orientation. A positive angle
* indicates that the major axis of contact is oriented to the right. A negative angle
* indicates that the major axis of contact is oriented to the left.
@@ -1737,34 +2192,40 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Returns a string that represents the symbolic name of the specified axis
- * such as "AXIS_X" or an equivalent numeric constants such as "42" if unknown.
+ * such as "AXIS_X" or an equivalent numeric constant such as "42" if unknown.
*
* @param axis The axis
* @return The symbolic name of the specified axis.
- * @hide
*/
public static String axisToString(int axis) {
- switch (axis) {
- case AXIS_X:
- return "AXIS_X";
- case AXIS_Y:
- return "AXIS_Y";
- case AXIS_PRESSURE:
- return "AXIS_PRESSURE";
- case AXIS_SIZE:
- return "AXIS_SIZE";
- case AXIS_TOUCH_MAJOR:
- return "AXIS_TOUCH_MAJOR";
- case AXIS_TOUCH_MINOR:
- return "AXIS_TOUCH_MINOR";
- case AXIS_TOOL_MAJOR:
- return "AXIS_TOOL_MAJOR";
- case AXIS_TOOL_MINOR:
- return "AXIS_TOOL_MINOR";
- case AXIS_ORIENTATION:
- return "AXIS_ORIENTATION";
- default:
- return Integer.toString(axis);
+ String symbolicName = AXIS_SYMBOLIC_NAMES.get(axis);
+ return symbolicName != null ? symbolicName : Integer.toString(axis);
+ }
+
+ /**
+ * Gets an axis by its symbolic name such as "KEYCODE_A" or an
+ * equivalent numeric constant such as "1001".
+ *
+ * @param symbolicName The symbolic name of the axis.
+ * @return The axis or -1 if not found.
+ * @see #keycodeToString
+ */
+ public static int axisFromString(String symbolicName) {
+ if (symbolicName == null) {
+ throw new IllegalArgumentException("symbolicName must not be null");
+ }
+
+ final int count = AXIS_SYMBOLIC_NAMES.size();
+ for (int i = 0; i < count; i++) {
+ if (symbolicName.equals(AXIS_SYMBOLIC_NAMES.valueAt(i))) {
+ return i;
+ }
+ }
+
+ try {
+ return Integer.parseInt(symbolicName, 10);
+ } catch (NumberFormatException ex) {
+ return -1;
}
}
@@ -1803,7 +2264,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
*/
public static final class PointerCoords {
private static final int INITIAL_PACKED_AXIS_VALUES = 8;
- private int mPackedAxisBits; // 32bits are enough for now, can raise to 64bit when needed
+ private long mPackedAxisBits;
private float[] mPackedAxisValues;
/**
@@ -1823,20 +2284,14 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
/**
- * The X coordinate of the pointer movement.
- * The interpretation of the X axis varies by input source.
- * It may represent the X position of the center of the touch contact area,
- * a relative horizontal displacement of a trackball or joystick, or something else.
+ * The X component of the pointer movement.
*
* @see MotionEvent#AXIS_X
*/
public float x;
/**
- * The Y coordinate of the pointer movement.
- * The interpretation of the Y axis varies by input source.
- * It may represent the Y position of the center of the touch contact area,
- * a relative vertical displacement of a trackball or joystick, or something else.
+ * The Y component of the pointer movement.
*
* @see MotionEvent#AXIS_Y
*/
@@ -1912,7 +2367,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* The orientation of the touch area and tool area in radians clockwise from vertical.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * An angle of 0 radians indicates that the major axis of contact is oriented
* upwards, is perfectly circular or is of unknown orientation. A positive angle
* indicates that the major axis of contact is oriented to the right. A negative angle
* indicates that the major axis of contact is oriented to the left.
@@ -1947,11 +2402,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param other The pointer coords object to copy.
*/
public void copyFrom(PointerCoords other) {
- final int bits = other.mPackedAxisBits;
+ final long bits = other.mPackedAxisBits;
mPackedAxisBits = bits;
if (bits != 0) {
final float[] otherValues = other.mPackedAxisValues;
- final int count = Integer.bitCount(bits);
+ final int count = Long.bitCount(bits);
float[] values = mPackedAxisValues;
if (values == null || count > values.length) {
values = new float[otherValues.length];
@@ -2001,12 +2456,15 @@ public final class MotionEvent extends InputEvent implements Parcelable {
case AXIS_ORIENTATION:
return orientation;
default: {
- final int bits = mPackedAxisBits;
- final int axisBit = 1 << axis;
+ if (axis < 0 || axis > 63) {
+ throw new IllegalArgumentException("Axis out of range.");
+ }
+ final long bits = mPackedAxisBits;
+ final long axisBit = 1L << axis;
if ((bits & axisBit) == 0) {
return 0;
}
- final int index = Integer.bitCount(bits & (axisBit - 1));
+ final int index = Long.bitCount(bits & (axisBit - 1L));
return mPackedAxisValues[index];
}
}
@@ -2051,16 +2509,19 @@ public final class MotionEvent extends InputEvent implements Parcelable {
orientation = value;
break;
default: {
- final int bits = mPackedAxisBits;
- final int axisBit = 1 << axis;
- final int index = Integer.bitCount(bits & (axisBit - 1));
+ if (axis < 0 || axis > 63) {
+ throw new IllegalArgumentException("Axis out of range.");
+ }
+ final long bits = mPackedAxisBits;
+ final long axisBit = 1L << axis;
+ final int index = Long.bitCount(bits & (axisBit - 1L));
float[] values = mPackedAxisValues;
if ((bits & axisBit) == 0) {
if (values == null) {
values = new float[INITIAL_PACKED_AXIS_VALUES];
mPackedAxisValues = values;
} else {
- final int count = Integer.bitCount(bits);
+ final int count = Long.bitCount(bits);
if (count < values.length) {
if (index != count) {
System.arraycopy(values, index, values, index + 1,
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ec1a373..39f99b8 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2496,7 +2496,6 @@ public final class ViewRoot extends Handler implements ViewParent,
// Deliver the event to the view.
if (mView.dispatchGenericMotionEvent(event)) {
- ensureTouchMode(false);
if (isJoystick) {
updateJoystickDirection(event, false);
}
@@ -2525,8 +2524,16 @@ public final class ViewRoot extends Handler implements ViewParent,
final int metaState = event.getMetaState();
final int deviceId = event.getDeviceId();
final int source = event.getSource();
- final int xDirection = joystickAxisValueToDirection(event.getX());
- final int yDirection = joystickAxisValueToDirection(event.getY());
+
+ int xDirection = joystickAxisValueToDirection(event.getAxisValue(MotionEvent.AXIS_HAT_X));
+ if (xDirection == 0) {
+ xDirection = joystickAxisValueToDirection(event.getX());
+ }
+
+ int yDirection = joystickAxisValueToDirection(event.getAxisValue(MotionEvent.AXIS_HAT_Y));
+ if (yDirection == 0) {
+ yDirection = joystickAxisValueToDirection(event.getY());
+ }
if (xDirection != mLastJoystickXDirection) {
if (mLastJoystickXKeyCode != 0) {
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 0b765fd..4a6857c 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -327,7 +327,10 @@ public class PointerLocationView extends View {
.append(" ToolMajor=").append(coords.toolMajor, 3)
.append(" ToolMinor=").append(coords.toolMinor, 3)
.append(" Orientation=").append((float)(coords.orientation * 180 / Math.PI), 1)
- .append("deg").toString());
+ .append("deg")
+ .append(" VScroll=").append(coords.getAxisValue(MotionEvent.AXIS_VSCROLL), 1)
+ .append(" HScroll=").append(coords.getAxisValue(MotionEvent.AXIS_HSCROLL), 1)
+ .toString());
}
public void addTouchEvent(MotionEvent event) {
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 069e40b..5ba1cff 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -207,8 +207,7 @@ static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
- uint32_t bits = env->GetIntField(pointerCoordsObj,
- gPointerCoordsClassInfo.mPackedAxisBits);
+ uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
if (bits) {
jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
gPointerCoordsClassInfo.mPackedAxisValues));
@@ -219,7 +218,7 @@ static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
uint32_t index = 0;
do {
uint32_t axis = __builtin_ctz(bits);
- uint32_t axisBit = 1 << axis;
+ uint64_t axisBit = 1LL << axis;
bits &= ~axisBit;
outRawPointerCoords->setAxisValue(axis, values[index++]);
} while (bits);
@@ -272,21 +271,21 @@ static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointer
env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
- const uint32_t unpackedAxisBits = 0
- | (1 << AMOTION_EVENT_AXIS_X)
- | (1 << AMOTION_EVENT_AXIS_Y)
- | (1 << AMOTION_EVENT_AXIS_PRESSURE)
- | (1 << AMOTION_EVENT_AXIS_SIZE)
- | (1 << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
- | (1 << AMOTION_EVENT_AXIS_TOUCH_MINOR)
- | (1 << AMOTION_EVENT_AXIS_TOOL_MAJOR)
- | (1 << AMOTION_EVENT_AXIS_TOOL_MINOR)
- | (1 << AMOTION_EVENT_AXIS_ORIENTATION);
-
- uint32_t outBits = 0;
- uint32_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
+ const uint64_t unpackedAxisBits = 0
+ | (1LL << AMOTION_EVENT_AXIS_X)
+ | (1LL << AMOTION_EVENT_AXIS_Y)
+ | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
+ | (1LL << AMOTION_EVENT_AXIS_SIZE)
+ | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
+ | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
+ | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
+ | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
+ | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
+
+ uint64_t outBits = 0;
+ uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
if (remainingBits) {
- uint32_t packedAxesCount = __builtin_popcount(remainingBits);
+ uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
outPointerCoordsObj);
if (!outValuesArray) {
@@ -300,7 +299,7 @@ static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointer
uint32_t index = 0;
do {
uint32_t axis = __builtin_ctz(remainingBits);
- uint32_t axisBit = 1 << axis;
+ uint64_t axisBit = 1LL << axis;
remainingBits &= ~axisBit;
outBits |= axisBit;
outValues[index++] = rawPointerCoords->getAxisValue(axis);
@@ -309,7 +308,7 @@ static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointer
env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
env->DeleteLocalRef(outValuesArray);
}
- env->SetIntField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
+ env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
}
@@ -758,7 +757,7 @@ int register_android_view_MotionEvent(JNIEnv* env) {
FIND_CLASS(gPointerCoordsClassInfo.clazz, "android/view/MotionEvent$PointerCoords");
GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, gPointerCoordsClassInfo.clazz,
- "mPackedAxisBits", "I");
+ "mPackedAxisBits", "J");
GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, gPointerCoordsClassInfo.clazz,
"mPackedAxisValues", "[F");
GET_FIELD_ID(gPointerCoordsClassInfo.x, gPointerCoordsClassInfo.clazz,
diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk
index 8cba52d..a66a884 100644
--- a/data/keyboards/Android.mk
+++ b/data/keyboards/Android.mk
@@ -17,3 +17,21 @@
LOCAL_PATH := $(call my-dir)
include $(LOCAL_PATH)/common.mk
+
+# Validate all key maps.
+include $(CLEAR_VARS)
+
+validatekeymaps := $(HOST_OUT_EXECUTABLES)/validatekeymaps$(HOST_EXECUTABLE_SUFFIX)
+files := \
+ $(foreach file,$(keylayouts),frameworks/base/data/keyboards/$(file)) \
+ $(foreach file,$(keycharmaps),frameworks/base/data/keyboards/$(file)) \
+ $(foreach file,$(keyconfigs),frameworks/base/data/keyboards/$(file))
+
+LOCAL_MODULE := validate_framework_keymaps
+LOCAL_MODULE_TAGS := optional
+LOCAL_REQUIRED_MODULES := validatekeymaps
+
+validate_framework_keymaps: $(files)
+ $(hide) $(validatekeymaps) $(files)
+
+include $(BUILD_PHONY_PACKAGE)
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 14d7c80..51a8b27 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -545,3 +545,129 @@ key ESCAPE {
meta: fallback HOME
alt: fallback MENU
}
+
+### Gamepad buttons ###
+
+key BUTTON_A {
+ base: fallback BACK
+}
+
+key BUTTON_B {
+ base: fallback BACK
+}
+
+key BUTTON_C {
+ base: fallback BACK
+}
+
+key BUTTON_X {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_Y {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_Z {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_L1 {
+ base: none
+}
+
+key BUTTON_R1 {
+ base: none
+}
+
+key BUTTON_L2 {
+ base: none
+}
+
+key BUTTON_R2 {
+ base: none
+}
+
+key BUTTON_THUMBL {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_THUMBR {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_START {
+ base: fallback HOME
+}
+
+key BUTTON_SELECT {
+ base: fallback MENU
+}
+
+key BUTTON_MODE {
+ base: fallback MENU
+}
+
+key BUTTON_1 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_2 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_3 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_4 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_5 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_6 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_7 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_8 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_9 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_10 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_11 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_12 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_13 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_14 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_15 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_16 {
+ base: fallback DPAD_CENTER
+}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 0aefc31..6d925d6 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -261,7 +261,6 @@ key 233 HEADSETHOOK
# key 239 "KEY_KBDILLUMUP"
# key 240 "KEY_UNKNOWN"
-
key 288 BUTTON_1
key 289 BUTTON_2
key 290 BUTTON_3
@@ -400,3 +399,16 @@ key 484 B FUNCTION
# key 502 KEY_BRL_DOT6
# key 503 KEY_BRL_DOT7
# key 504 KEY_BRL_DOT8
+
+
+# Joystick and game controller axes.
+# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x03 RX
+axis 0x04 RY
+axis 0x05 RZ
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+ \ No newline at end of file
diff --git a/data/keyboards/Vendor_046d_Product_c216.kl b/data/keyboards/Vendor_046d_Product_c216.kl
new file mode 100644
index 0000000..6743323
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_c216.kl
@@ -0,0 +1,37 @@
+# Copyright (C) 2011 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.
+
+#
+# Logitech Dual Action Controller
+#
+
+key 0x120 BUTTON_A
+key 0x123 BUTTON_B
+key 0x121 BUTTON_X
+key 0x122 BUTTON_Y
+key 0x124 BUTTON_L1
+key 0x125 BUTTON_R1
+key 0x126 BUTTON_L2
+key 0x127 BUTTON_R2
+key 0x128 BUTTON_SELECT
+key 0x129 BUTTON_START
+key 0x12a BUTTON_THUMBL
+key 0x12b BUTTON_THUMBR
+
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x05 RZ
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
diff --git a/data/keyboards/Vendor_054c_Product_0268.kl b/data/keyboards/Vendor_054c_Product_0268.kl
new file mode 100644
index 0000000..f8ac6a3
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268.kl
@@ -0,0 +1,76 @@
+# Copyright (C) 2011 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.
+
+#
+# Sony Playstation(R)3 Controller
+#
+
+key 0x124 DPAD_UP
+key 0x125 DPAD_RIGHT
+key 0x126 DPAD_DOWN
+key 0x127 DPAD_LEFT
+
+key 0x120 BUTTON_SELECT
+key 0x123 BUTTON_START
+key 0x12f BUTTON_A
+key 0x12c BUTTON_B
+key 0x12e BUTTON_X
+key 0x12d BUTTON_Y
+key 0x12a BUTTON_L1
+key 0x12b BUTTON_R1
+key 0x128 BUTTON_L2
+key 0x129 BUTTON_R2
+key 0x121 BUTTON_THUMBL
+key 0x122 BUTTON_THUMBR
+
+# PS key
+key 0x2d0 BUTTON_1
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+
+# Right Analog Stick
+axis 0x02 Z
+axis 0x05 RZ
+
+# DPAD
+# axis 0x2c -HAT_Y
+# axis 0x2d +HAT_X
+# axis 0x2e +HAT_Y
+# axis 0x2f -HAT_X
+
+# L2 trigger
+axis 0x30 LTRIGGER
+
+# R2 trigger
+axis 0x31 RTRIGGER
+
+# L1 trigger
+# axis 0x32
+
+# R1 trigger
+# axis 0x33
+
+# Triangle
+# axis 0x34
+
+# Circle
+# axis 0x35
+
+# Cross
+# axis 0x36
+
+# Square
+# axis 0x37
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
index 56c287a..5b367b9 100644
--- a/data/keyboards/common.mk
+++ b/data/keyboards/common.mk
@@ -19,7 +19,9 @@ keylayouts := \
Generic.kl \
AVRCP.kl \
qwerty.kl \
+ Vendor_046d_Product_c216.kl \
Vendor_046d_Product_c532.kl \
+ Vendor_054c_Product_0268.kl \
Vendor_05ac_Product_0239.kl \
Vendor_22b8_Product_093d.kl
diff --git a/include/ui/Input.h b/include/ui/Input.h
index cb9327e..86ce098 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -170,10 +170,10 @@ struct InputConfiguration {
* Pointer coordinate data.
*/
struct PointerCoords {
- enum { MAX_AXES = 15 }; // 15 so that sizeof(PointerCoords) == 16 * 4 == 64
+ enum { MAX_AXES = 14 }; // 14 so that sizeof(PointerCoords) == 64
// Bitfield of axes that are present in this structure.
- uint32_t bits; // 32bits are enough for now, can raise to 64bit when needed
+ uint64_t bits;
// Values of axes that are stored in this structure packed in order by axis id
// for each axis that is present in the structure according to 'bits'.
@@ -183,41 +183,9 @@ struct PointerCoords {
bits = 0;
}
- inline float getAxisValue(int32_t axis) const {
- uint32_t axisBit = 1 << axis;
- if (!(bits & axisBit)) {
- return 0;
- }
- uint32_t index = __builtin_popcount(bits & (axisBit - 1));
- return values[index];
- }
-
- inline status_t setAxisValue(int32_t axis, float value) {
- uint32_t axisBit = 1 << axis;
- uint32_t index = __builtin_popcount(bits & (axisBit - 1));
- if (!(bits & axisBit)) {
- uint32_t count = __builtin_popcount(bits);
- if (count >= MAX_AXES) {
- tooManyAxes(axis);
- return NO_MEMORY;
- }
- bits |= axisBit;
- for (uint32_t i = count; i > index; i--) {
- values[i] = values[i - 1];
- }
- }
- values[index] = value;
- return OK;
- }
-
- inline float* editAxisValue(int32_t axis) {
- uint32_t axisBit = 1 << axis;
- if (!(bits & axisBit)) {
- return NULL;
- }
- uint32_t index = __builtin_popcount(bits & (axisBit - 1));
- return &values[index];
- }
+ float getAxisValue(int32_t axis) const;
+ status_t setAxisValue(int32_t axis, float value);
+ float* editAxisValue(int32_t axis);
#ifdef HAVE_ANDROID_OS
status_t readFromParcel(Parcel* parcel);
diff --git a/include/ui/KeyLayoutMap.h b/include/ui/KeyLayoutMap.h
index f0a6d00..904c8f3 100644
--- a/include/ui/KeyLayoutMap.h
+++ b/include/ui/KeyLayoutMap.h
@@ -25,7 +25,7 @@
namespace android {
/**
- * Describes a mapping from keyboard scan codes to Android key codes.
+ * Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes.
*/
class KeyLayoutMap {
public:
@@ -33,8 +33,10 @@ public:
static status_t load(const String8& filename, KeyLayoutMap** outMap);
- status_t map(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const;
- status_t findScanCodes(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
+ status_t mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const;
+ status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
+
+ status_t mapAxis(int32_t scanCode, int32_t* axis) const;
private:
struct Key {
@@ -42,7 +44,8 @@ private:
uint32_t flags;
};
- KeyedVector<int32_t,Key> mKeys;
+ KeyedVector<int32_t, Key> mKeys;
+ KeyedVector<int32_t, int32_t> mAxes;
KeyLayoutMap();
@@ -57,6 +60,7 @@ private:
private:
status_t parseKey();
+ status_t parseAxis();
};
};
diff --git a/include/ui/Keyboard.h b/include/ui/Keyboard.h
index 50296e2..54bc968 100644
--- a/include/ui/Keyboard.h
+++ b/include/ui/Keyboard.h
@@ -111,6 +111,18 @@ extern int32_t getKeyCodeByLabel(const char* label);
extern uint32_t getKeyFlagByLabel(const char* label);
/**
+ * Gets a axis by its short form label, eg. "X".
+ * Returns -1 if unknown.
+ */
+extern int32_t getAxisByLabel(const char* label);
+
+/**
+ * Gets a axis label by its id.
+ * Returns NULL if unknown.
+ */
+extern const char* getAxisLabel(int32_t axisId);
+
+/**
* Updates a meta state field when a key is pressed or released.
*/
extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index dbccf29..bdfbf7c 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -250,4 +250,47 @@ static const KeycodeLabel FLAGS[] = {
{ NULL, 0 }
};
+static const KeycodeLabel AXES[] = {
+ { "X", 0 },
+ { "Y", 1 },
+ { "PRESSURE", 2 },
+ { "SIZE", 3 },
+ { "TOUCH_MAJOR", 4 },
+ { "TOUCH_MINOR", 5 },
+ { "TOOL_MAJOR", 6 },
+ { "TOOL_MINOR", 7 },
+ { "ORIENTATION", 8 },
+ { "VSCROLL", 9 },
+ { "HSCROLL", 10 },
+ { "Z", 11 },
+ { "RX", 12 },
+ { "RY", 13 },
+ { "RZ", 14 },
+ { "HAT_X", 15 },
+ { "HAT_Y", 16 },
+ { "LTRIGGER", 17 },
+ { "RTRIGGER", 18 },
+ { "GENERIC_1", 32 },
+ { "GENERIC_2", 33 },
+ { "GENERIC_3", 34 },
+ { "GENERIC_4", 35 },
+ { "GENERIC_5", 36 },
+ { "GENERIC_6", 37 },
+ { "GENERIC_7", 38 },
+ { "GENERIC_8", 39 },
+ { "GENERIC_9", 40 },
+ { "GENERIC_10", 41 },
+ { "GENERIC_11", 42 },
+ { "GENERIC_12", 43 },
+ { "GENERIC_13", 44 },
+ { "GENERIC_14", 45 },
+ { "GENERIC_15", 46 },
+ { "GENERIC_16", 47 },
+
+ // NOTE: If you add a new axis here you must also add it to several other files.
+ // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
+
+ { NULL, -1 }
+};
+
#endif // _UI_KEYCODE_LABELS_H
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index e3107d5..a80320e 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -250,11 +250,59 @@ void KeyEvent::initialize(const KeyEvent& from) {
// --- PointerCoords ---
+float PointerCoords::getAxisValue(int32_t axis) const {
+ if (axis < 0 || axis > 63) {
+ return 0;
+ }
+
+ uint64_t axisBit = 1LL << axis;
+ if (!(bits & axisBit)) {
+ return 0;
+ }
+ uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
+ return values[index];
+}
+
+status_t PointerCoords::setAxisValue(int32_t axis, float value) {
+ if (axis < 0 || axis > 63) {
+ return NAME_NOT_FOUND;
+ }
+
+ uint64_t axisBit = 1LL << axis;
+ uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
+ if (!(bits & axisBit)) {
+ uint32_t count = __builtin_popcountll(bits);
+ if (count >= MAX_AXES) {
+ tooManyAxes(axis);
+ return NO_MEMORY;
+ }
+ bits |= axisBit;
+ for (uint32_t i = count; i > index; i--) {
+ values[i] = values[i - 1];
+ }
+ }
+ values[index] = value;
+ return OK;
+}
+
+float* PointerCoords::editAxisValue(int32_t axis) {
+ if (axis < 0 || axis > 63) {
+ return NULL;
+ }
+
+ uint64_t axisBit = 1LL << axis;
+ if (!(bits & axisBit)) {
+ return NULL;
+ }
+ uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
+ return &values[index];
+}
+
#ifdef HAVE_ANDROID_OS
status_t PointerCoords::readFromParcel(Parcel* parcel) {
- bits = parcel->readInt32();
+ bits = parcel->readInt64();
- uint32_t count = __builtin_popcount(bits);
+ uint32_t count = __builtin_popcountll(bits);
if (count > MAX_AXES) {
return BAD_VALUE;
}
@@ -266,9 +314,9 @@ status_t PointerCoords::readFromParcel(Parcel* parcel) {
}
status_t PointerCoords::writeToParcel(Parcel* parcel) const {
- parcel->writeInt32(bits);
+ parcel->writeInt64(bits);
- uint32_t count = __builtin_popcount(bits);
+ uint32_t count = __builtin_popcountll(bits);
for (uint32_t i = 0; i < count; i++) {
parcel->writeInt32(values[i]);
}
diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp
index 56bc26f..2ed0e66 100644
--- a/libs/ui/KeyLayoutMap.cpp
+++ b/libs/ui/KeyLayoutMap.cpp
@@ -82,11 +82,11 @@ status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) {
return status;
}
-status_t KeyLayoutMap::map(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const {
+status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const {
ssize_t index = mKeys.indexOfKey(scanCode);
if (index < 0) {
#if DEBUG_MAPPING
- LOGD("map: scanCode=%d ~ Failed.", scanCode);
+ LOGD("mapKey: scanCode=%d ~ Failed.", scanCode);
#endif
*keyCode = AKEYCODE_UNKNOWN;
*flags = 0;
@@ -98,12 +98,12 @@ status_t KeyLayoutMap::map(int32_t scanCode, int32_t* keyCode, uint32_t* flags)
*flags = k.flags;
#if DEBUG_MAPPING
- LOGD("map: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags);
+ LOGD("mapKey: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags);
#endif
return NO_ERROR;
}
-status_t KeyLayoutMap::findScanCodes(int32_t keyCode, Vector<int32_t>* outScanCodes) const {
+status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const {
const size_t N = mKeys.size();
for (size_t i=0; i<N; i++) {
if (mKeys.valueAt(i).keyCode == keyCode) {
@@ -113,6 +113,25 @@ status_t KeyLayoutMap::findScanCodes(int32_t keyCode, Vector<int32_t>* outScanCo
return NO_ERROR;
}
+status_t KeyLayoutMap::mapAxis(int32_t scanCode, int32_t* axis) const {
+ ssize_t index = mAxes.indexOfKey(scanCode);
+ if (index < 0) {
+#if DEBUG_MAPPING
+ LOGD("mapAxis: scanCode=%d ~ Failed.", scanCode);
+#endif
+ *axis = -1;
+ return NAME_NOT_FOUND;
+ }
+
+ *axis = mAxes.valueAt(index);
+
+#if DEBUG_MAPPING
+ LOGD("mapAxis: scanCode=%d ~ Result axis=%d.", scanCode, *axis);
+#endif
+ return NO_ERROR;
+}
+
+
// --- KeyLayoutMap::Parser ---
KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) :
@@ -137,6 +156,10 @@ status_t KeyLayoutMap::Parser::parse() {
mTokenizer->skipDelimiters(WHITESPACE);
status_t status = parseKey();
if (status) return status;
+ } else if (keywordToken == "axis") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ status_t status = parseAxis();
+ if (status) return status;
} else {
LOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
keywordToken.string());
@@ -162,12 +185,12 @@ status_t KeyLayoutMap::Parser::parseKey() {
char* end;
int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
if (*end) {
- LOGE("%s: Expected scan code number, got '%s'.", mTokenizer->getLocation().string(),
+ LOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(),
scanCodeToken.string());
return BAD_VALUE;
}
if (mMap->mKeys.indexOfKey(scanCode) >= 0) {
- LOGE("%s: Duplicate entry for scan code '%s'.", mTokenizer->getLocation().string(),
+ LOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(),
scanCodeToken.string());
return BAD_VALUE;
}
@@ -189,12 +212,12 @@ status_t KeyLayoutMap::Parser::parseKey() {
String8 flagToken = mTokenizer->nextToken(WHITESPACE);
uint32_t flag = getKeyFlagByLabel(flagToken.string());
if (!flag) {
- LOGE("%s: Expected flag label, got '%s'.", mTokenizer->getLocation().string(),
+ LOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
flagToken.string());
return BAD_VALUE;
}
if (flags & flag) {
- LOGE("%s: Duplicate flag '%s'.", mTokenizer->getLocation().string(),
+ LOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
flagToken.string());
return BAD_VALUE;
}
@@ -211,4 +234,35 @@ status_t KeyLayoutMap::Parser::parseKey() {
return NO_ERROR;
}
+status_t KeyLayoutMap::Parser::parseAxis() {
+ String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
+ char* end;
+ int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
+ if (*end) {
+ LOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
+ scanCodeToken.string());
+ return BAD_VALUE;
+ }
+ if (mMap->mAxes.indexOfKey(scanCode) >= 0) {
+ LOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
+ scanCodeToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 axisToken = mTokenizer->nextToken(WHITESPACE);
+ int32_t axis = getAxisByLabel(axisToken.string());
+ if (axis < 0) {
+ LOGE("%s: Expected axis label, got '%s'.", mTokenizer->getLocation().string(),
+ axisToken.string());
+ return BAD_VALUE;
+ }
+
+#if DEBUG_PARSER
+ LOGD("Parsed axis: scanCode=%d, axis=%d.", scanCode, axis);
+#endif
+ mMap->mAxes.add(scanCode, axis);
+ return NO_ERROR;
+}
+
};
diff --git a/libs/ui/Keyboard.cpp b/libs/ui/Keyboard.cpp
index 6faa600..8b6300a 100644
--- a/libs/ui/Keyboard.cpp
+++ b/libs/ui/Keyboard.cpp
@@ -217,7 +217,7 @@ status_t getKeyCharacterMapFile(int32_t deviceId, String8& outKeyCharacterMapFil
return NAME_NOT_FOUND;
}
-static int lookupLabel(const char* literal, const KeycodeLabel *list) {
+static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) {
while (list->literal) {
if (strcmp(literal, list->literal) == 0) {
return list->value;
@@ -227,12 +227,30 @@ static int lookupLabel(const char* literal, const KeycodeLabel *list) {
return list->value;
}
+static const char* lookupLabelByValue(int value, const KeycodeLabel *list) {
+ while (list->literal) {
+ if (list->value == value) {
+ return list->literal;
+ }
+ list++;
+ }
+ return NULL;
+}
+
int32_t getKeyCodeByLabel(const char* label) {
- return int32_t(lookupLabel(label, KEYCODES));
+ return int32_t(lookupValueByLabel(label, KEYCODES));
}
uint32_t getKeyFlagByLabel(const char* label) {
- return uint32_t(lookupLabel(label, FLAGS));
+ return uint32_t(lookupValueByLabel(label, FLAGS));
+}
+
+int32_t getAxisByLabel(const char* label) {
+ return int32_t(lookupValueByLabel(label, AXES));
+}
+
+const char* getAxisLabel(int32_t axisId) {
+ return lookupLabelByValue(axisId, AXES);
}
static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp
index 7b15c38..b77489e 100644
--- a/libs/ui/tests/InputEvent_test.cpp
+++ b/libs/ui/tests/InputEvent_test.cpp
@@ -18,6 +18,9 @@
#include <gtest/gtest.h>
#include <binder/Parcel.h>
+#include <math.h>
+#include <SkMatrix.h>
+
namespace android {
class BaseTest : public testing::Test {
@@ -35,7 +38,7 @@ TEST_F(PointerCoordsTest, ClearSetsBitsToZero) {
PointerCoords coords;
coords.clear();
- ASSERT_EQ(0U, coords.bits);
+ ASSERT_EQ(0ULL, coords.bits);
}
TEST_F(PointerCoordsTest, AxisValues) {
@@ -54,7 +57,7 @@ TEST_F(PointerCoordsTest, AxisValues) {
// Set first axis.
ASSERT_EQ(OK, coords.setAxisValue(1, 5));
- ASSERT_EQ(0x00000002U, coords.bits);
+ ASSERT_EQ(0x00000002ULL, coords.bits);
ASSERT_EQ(5, coords.values[0]);
ASSERT_EQ(0, coords.getAxisValue(0))
@@ -64,7 +67,7 @@ TEST_F(PointerCoordsTest, AxisValues) {
// Set an axis with a higher id than all others. (appending value at the end)
ASSERT_EQ(OK, coords.setAxisValue(3, 2));
- ASSERT_EQ(0x0000000aU, coords.bits);
+ ASSERT_EQ(0x0000000aULL, coords.bits);
ASSERT_EQ(5, coords.values[0]);
ASSERT_EQ(2, coords.values[1]);
@@ -79,7 +82,7 @@ TEST_F(PointerCoordsTest, AxisValues) {
// Set an axis with an id lower than all others. (prepending value at beginning)
ASSERT_EQ(OK, coords.setAxisValue(0, 4));
- ASSERT_EQ(0x0000000bU, coords.bits);
+ ASSERT_EQ(0x0000000bULL, coords.bits);
ASSERT_EQ(4, coords.values[0]);
ASSERT_EQ(5, coords.values[1]);
ASSERT_EQ(2, coords.values[2]);
@@ -104,7 +107,7 @@ TEST_F(PointerCoordsTest, AxisValues) {
// Set an axis with an id between the others. (inserting value in the middle)
ASSERT_EQ(OK, coords.setAxisValue(2, 1));
- ASSERT_EQ(0x0000000fU, coords.bits);
+ ASSERT_EQ(0x0000000fULL, coords.bits);
ASSERT_EQ(4, coords.values[0]);
ASSERT_EQ(7, coords.values[1]);
ASSERT_EQ(1, coords.values[2]);
@@ -121,7 +124,7 @@ TEST_F(PointerCoordsTest, AxisValues) {
// Set an existing axis value in place.
ASSERT_EQ(OK, coords.setAxisValue(1, 6));
- ASSERT_EQ(0x0000000fU, coords.bits);
+ ASSERT_EQ(0x0000000fULL, coords.bits);
ASSERT_EQ(4, coords.values[0]);
ASSERT_EQ(6, coords.values[1]);
ASSERT_EQ(1, coords.values[2]);
@@ -140,15 +143,15 @@ TEST_F(PointerCoordsTest, AxisValues) {
for (size_t axis = 4; axis < PointerCoords::MAX_AXES; axis++) {
ASSERT_EQ(OK, coords.setAxisValue(axis, axis));
}
- ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcount(coords.bits));
+ ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits));
// Try to set one more axis beyond maximum number.
// Ensure bits are unchanged.
ASSERT_EQ(NO_MEMORY, coords.setAxisValue(PointerCoords::MAX_AXES, 100));
- ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcount(coords.bits));
+ ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits));
}
-TEST_F(PointerCoordsTest, ReadAndWriteParcel) {
+TEST_F(PointerCoordsTest, Parcel) {
Parcel parcel;
PointerCoords inCoords;
@@ -160,7 +163,7 @@ TEST_F(PointerCoordsTest, ReadAndWriteParcel) {
parcel.setDataPosition(0);
outCoords.readFromParcel(&parcel);
- ASSERT_EQ(0U, outCoords.bits);
+ ASSERT_EQ(0ULL, outCoords.bits);
// Round trip with some values.
parcel.freeData();
@@ -213,16 +216,22 @@ TEST_F(KeyEventTest, Properties) {
// --- MotionEventTest ---
class MotionEventTest : public BaseTest {
+protected:
+ static const nsecs_t ARBITRARY_DOWN_TIME;
+ static const nsecs_t ARBITRARY_EVENT_TIME;
+ static const float X_OFFSET;
+ static const float Y_OFFSET;
+
+ void initializeEventWithHistory(MotionEvent* event);
+ void assertEqualsEventWithHistory(const MotionEvent* event);
};
-TEST_F(MotionEventTest, Properties) {
- MotionEvent event;
+const nsecs_t MotionEventTest::ARBITRARY_DOWN_TIME = 1;
+const nsecs_t MotionEventTest::ARBITRARY_EVENT_TIME = 2;
+const float MotionEventTest::X_OFFSET = 1.0f;
+const float MotionEventTest::Y_OFFSET = 1.1f;
- // Initialize, add samples and get properties.
- const nsecs_t ARBITRARY_DOWN_TIME = 1;
- const nsecs_t ARBITRARY_EVENT_TIME = 2;
- const float X_OFFSET = 1.0f;
- const float Y_OFFSET = 1.1f;
+void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
int32_t pointerIds[] = { 1, 2 };
PointerCoords pointerCoords[2];
pointerCoords[0].clear();
@@ -245,7 +254,7 @@ TEST_F(MotionEventTest, Properties) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
- event.initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
+ event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON,
X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
@@ -270,7 +279,7 @@ TEST_F(MotionEventTest, Properties) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128);
- event.addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords);
+ event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211);
@@ -290,128 +299,284 @@ TEST_F(MotionEventTest, Properties) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228);
- event.addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords);
-
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event.getType());
- ASSERT_EQ(2, event.getDeviceId());
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event.getSource());
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event.getAction());
- ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event.getFlags());
- ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event.getEdgeFlags());
- ASSERT_EQ(AMETA_ALT_ON, event.getMetaState());
- ASSERT_EQ(X_OFFSET, event.getXOffset());
- ASSERT_EQ(Y_OFFSET, event.getYOffset());
- ASSERT_EQ(2.0f, event.getXPrecision());
- ASSERT_EQ(2.1f, event.getYPrecision());
- ASSERT_EQ(ARBITRARY_DOWN_TIME, event.getDownTime());
-
- ASSERT_EQ(2U, event.getPointerCount());
- ASSERT_EQ(1, event.getPointerId(0));
- ASSERT_EQ(2, event.getPointerId(1));
-
- ASSERT_EQ(2U, event.getHistorySize());
-
- // Get data.
- ASSERT_EQ(ARBITRARY_EVENT_TIME, event.getHistoricalEventTime(0));
- ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event.getHistoricalEventTime(1));
- ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event.getEventTime());
+ event->addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords);
+}
- ASSERT_EQ(11, event.getHistoricalRawPointerCoords(0, 0)->
+void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
+ // Check properties.
+ ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
+ ASSERT_EQ(2, event->getDeviceId());
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
+ ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
+ ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
+ ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
+ ASSERT_EQ(X_OFFSET, event->getXOffset());
+ ASSERT_EQ(Y_OFFSET, event->getYOffset());
+ ASSERT_EQ(2.0f, event->getXPrecision());
+ ASSERT_EQ(2.1f, event->getYPrecision());
+ ASSERT_EQ(ARBITRARY_DOWN_TIME, event->getDownTime());
+
+ ASSERT_EQ(2U, event->getPointerCount());
+ ASSERT_EQ(1, event->getPointerId(0));
+ ASSERT_EQ(2, event->getPointerId(1));
+
+ ASSERT_EQ(2U, event->getHistorySize());
+
+ // Check data.
+ ASSERT_EQ(ARBITRARY_EVENT_TIME, event->getHistoricalEventTime(0));
+ ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1));
+ ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime());
+
+ ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(21, event.getHistoricalRawPointerCoords(1, 0)->
+ ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(111, event.getHistoricalRawPointerCoords(0, 1)->
+ ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(121, event.getHistoricalRawPointerCoords(1, 1)->
+ ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(211, event.getRawPointerCoords(0)->
+ ASSERT_EQ(211, event->getRawPointerCoords(0)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(221, event.getRawPointerCoords(1)->
+ ASSERT_EQ(221, event->getRawPointerCoords(1)->
getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(11, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
- ASSERT_EQ(21, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
- ASSERT_EQ(111, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
- ASSERT_EQ(121, event.getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
- ASSERT_EQ(211, event.getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
- ASSERT_EQ(221, event.getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
-
- ASSERT_EQ(10, event.getHistoricalRawX(0, 0));
- ASSERT_EQ(20, event.getHistoricalRawX(1, 0));
- ASSERT_EQ(110, event.getHistoricalRawX(0, 1));
- ASSERT_EQ(120, event.getHistoricalRawX(1, 1));
- ASSERT_EQ(210, event.getRawX(0));
- ASSERT_EQ(220, event.getRawX(1));
-
- ASSERT_EQ(11, event.getHistoricalRawY(0, 0));
- ASSERT_EQ(21, event.getHistoricalRawY(1, 0));
- ASSERT_EQ(111, event.getHistoricalRawY(0, 1));
- ASSERT_EQ(121, event.getHistoricalRawY(1, 1));
- ASSERT_EQ(211, event.getRawY(0));
- ASSERT_EQ(221, event.getRawY(1));
-
- ASSERT_EQ(X_OFFSET + 10, event.getHistoricalX(0, 0));
- ASSERT_EQ(X_OFFSET + 20, event.getHistoricalX(1, 0));
- ASSERT_EQ(X_OFFSET + 110, event.getHistoricalX(0, 1));
- ASSERT_EQ(X_OFFSET + 120, event.getHistoricalX(1, 1));
- ASSERT_EQ(X_OFFSET + 210, event.getX(0));
- ASSERT_EQ(X_OFFSET + 220, event.getX(1));
-
- ASSERT_EQ(Y_OFFSET + 11, event.getHistoricalY(0, 0));
- ASSERT_EQ(Y_OFFSET + 21, event.getHistoricalY(1, 0));
- ASSERT_EQ(Y_OFFSET + 111, event.getHistoricalY(0, 1));
- ASSERT_EQ(Y_OFFSET + 121, event.getHistoricalY(1, 1));
- ASSERT_EQ(Y_OFFSET + 211, event.getY(0));
- ASSERT_EQ(Y_OFFSET + 221, event.getY(1));
-
- ASSERT_EQ(12, event.getHistoricalPressure(0, 0));
- ASSERT_EQ(22, event.getHistoricalPressure(1, 0));
- ASSERT_EQ(112, event.getHistoricalPressure(0, 1));
- ASSERT_EQ(122, event.getHistoricalPressure(1, 1));
- ASSERT_EQ(212, event.getPressure(0));
- ASSERT_EQ(222, event.getPressure(1));
+ ASSERT_EQ(11, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
+ ASSERT_EQ(21, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
+ ASSERT_EQ(111, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
+ ASSERT_EQ(121, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
+ ASSERT_EQ(211, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
+ ASSERT_EQ(221, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
+
+ ASSERT_EQ(10, event->getHistoricalRawX(0, 0));
+ ASSERT_EQ(20, event->getHistoricalRawX(1, 0));
+ ASSERT_EQ(110, event->getHistoricalRawX(0, 1));
+ ASSERT_EQ(120, event->getHistoricalRawX(1, 1));
+ ASSERT_EQ(210, event->getRawX(0));
+ ASSERT_EQ(220, event->getRawX(1));
+
+ ASSERT_EQ(11, event->getHistoricalRawY(0, 0));
+ ASSERT_EQ(21, event->getHistoricalRawY(1, 0));
+ ASSERT_EQ(111, event->getHistoricalRawY(0, 1));
+ ASSERT_EQ(121, event->getHistoricalRawY(1, 1));
+ ASSERT_EQ(211, event->getRawY(0));
+ ASSERT_EQ(221, event->getRawY(1));
+
+ ASSERT_EQ(X_OFFSET + 10, event->getHistoricalX(0, 0));
+ ASSERT_EQ(X_OFFSET + 20, event->getHistoricalX(1, 0));
+ ASSERT_EQ(X_OFFSET + 110, event->getHistoricalX(0, 1));
+ ASSERT_EQ(X_OFFSET + 120, event->getHistoricalX(1, 1));
+ ASSERT_EQ(X_OFFSET + 210, event->getX(0));
+ ASSERT_EQ(X_OFFSET + 220, event->getX(1));
+
+ ASSERT_EQ(Y_OFFSET + 11, event->getHistoricalY(0, 0));
+ ASSERT_EQ(Y_OFFSET + 21, event->getHistoricalY(1, 0));
+ ASSERT_EQ(Y_OFFSET + 111, event->getHistoricalY(0, 1));
+ ASSERT_EQ(Y_OFFSET + 121, event->getHistoricalY(1, 1));
+ ASSERT_EQ(Y_OFFSET + 211, event->getY(0));
+ ASSERT_EQ(Y_OFFSET + 221, event->getY(1));
+
+ ASSERT_EQ(12, event->getHistoricalPressure(0, 0));
+ ASSERT_EQ(22, event->getHistoricalPressure(1, 0));
+ ASSERT_EQ(112, event->getHistoricalPressure(0, 1));
+ ASSERT_EQ(122, event->getHistoricalPressure(1, 1));
+ ASSERT_EQ(212, event->getPressure(0));
+ ASSERT_EQ(222, event->getPressure(1));
+
+ ASSERT_EQ(13, event->getHistoricalSize(0, 0));
+ ASSERT_EQ(23, event->getHistoricalSize(1, 0));
+ ASSERT_EQ(113, event->getHistoricalSize(0, 1));
+ ASSERT_EQ(123, event->getHistoricalSize(1, 1));
+ ASSERT_EQ(213, event->getSize(0));
+ ASSERT_EQ(223, event->getSize(1));
+
+ ASSERT_EQ(14, event->getHistoricalTouchMajor(0, 0));
+ ASSERT_EQ(24, event->getHistoricalTouchMajor(1, 0));
+ ASSERT_EQ(114, event->getHistoricalTouchMajor(0, 1));
+ ASSERT_EQ(124, event->getHistoricalTouchMajor(1, 1));
+ ASSERT_EQ(214, event->getTouchMajor(0));
+ ASSERT_EQ(224, event->getTouchMajor(1));
+
+ ASSERT_EQ(15, event->getHistoricalTouchMinor(0, 0));
+ ASSERT_EQ(25, event->getHistoricalTouchMinor(1, 0));
+ ASSERT_EQ(115, event->getHistoricalTouchMinor(0, 1));
+ ASSERT_EQ(125, event->getHistoricalTouchMinor(1, 1));
+ ASSERT_EQ(215, event->getTouchMinor(0));
+ ASSERT_EQ(225, event->getTouchMinor(1));
+
+ ASSERT_EQ(16, event->getHistoricalToolMajor(0, 0));
+ ASSERT_EQ(26, event->getHistoricalToolMajor(1, 0));
+ ASSERT_EQ(116, event->getHistoricalToolMajor(0, 1));
+ ASSERT_EQ(126, event->getHistoricalToolMajor(1, 1));
+ ASSERT_EQ(216, event->getToolMajor(0));
+ ASSERT_EQ(226, event->getToolMajor(1));
+
+ ASSERT_EQ(17, event->getHistoricalToolMinor(0, 0));
+ ASSERT_EQ(27, event->getHistoricalToolMinor(1, 0));
+ ASSERT_EQ(117, event->getHistoricalToolMinor(0, 1));
+ ASSERT_EQ(127, event->getHistoricalToolMinor(1, 1));
+ ASSERT_EQ(217, event->getToolMinor(0));
+ ASSERT_EQ(227, event->getToolMinor(1));
+
+ ASSERT_EQ(18, event->getHistoricalOrientation(0, 0));
+ ASSERT_EQ(28, event->getHistoricalOrientation(1, 0));
+ ASSERT_EQ(118, event->getHistoricalOrientation(0, 1));
+ ASSERT_EQ(128, event->getHistoricalOrientation(1, 1));
+ ASSERT_EQ(218, event->getOrientation(0));
+ ASSERT_EQ(228, event->getOrientation(1));
+}
+
+TEST_F(MotionEventTest, Properties) {
+ MotionEvent event;
+
+ // Initialize, add samples and check properties.
+ initializeEventWithHistory(&event);
+ ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event));
+
+ // Set source.
+ event.setSource(AINPUT_SOURCE_JOYSTICK);
+ ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+
+ // Set action.
+ event.setAction(AMOTION_EVENT_ACTION_CANCEL);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
+
+ // Set meta state.
+ event.setMetaState(AMETA_CTRL_ON);
+ ASSERT_EQ(AMETA_CTRL_ON, event.getMetaState());
+}
+
+TEST_F(MotionEventTest, CopyFrom_KeepHistory) {
+ MotionEvent event;
+ initializeEventWithHistory(&event);
+
+ MotionEvent copy;
+ copy.copyFrom(&event, true /*keepHistory*/);
+
+ ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event));
+}
+
+TEST_F(MotionEventTest, CopyFrom_DoNotKeepHistory) {
+ MotionEvent event;
+ initializeEventWithHistory(&event);
+
+ MotionEvent copy;
+ copy.copyFrom(&event, false /*keepHistory*/);
+
+ ASSERT_EQ(event.getPointerCount(), copy.getPointerCount());
+ ASSERT_EQ(0U, copy.getHistorySize());
+
+ ASSERT_EQ(event.getPointerId(0), copy.getPointerId(0));
+ ASSERT_EQ(event.getPointerId(1), copy.getPointerId(1));
+
+ ASSERT_EQ(event.getEventTime(), copy.getEventTime());
+
+ ASSERT_EQ(event.getX(0), copy.getX(0));
+}
+
+TEST_F(MotionEventTest, OffsetLocation) {
+ MotionEvent event;
+ initializeEventWithHistory(&event);
+
+ event.offsetLocation(5.0f, -2.0f);
+
+ ASSERT_EQ(X_OFFSET + 5.0f, event.getXOffset());
+ ASSERT_EQ(Y_OFFSET - 2.0f, event.getYOffset());
+}
+
+TEST_F(MotionEventTest, Scale) {
+ MotionEvent event;
+ initializeEventWithHistory(&event);
- ASSERT_EQ(13, event.getHistoricalSize(0, 0));
- ASSERT_EQ(23, event.getHistoricalSize(1, 0));
- ASSERT_EQ(113, event.getHistoricalSize(0, 1));
- ASSERT_EQ(123, event.getHistoricalSize(1, 1));
+ event.scale(2.0f);
+
+ ASSERT_EQ(X_OFFSET * 2, event.getXOffset());
+ ASSERT_EQ(Y_OFFSET * 2, event.getYOffset());
+
+ ASSERT_EQ(210 * 2, event.getRawX(0));
+ ASSERT_EQ(211 * 2, event.getRawY(0));
+ ASSERT_EQ((X_OFFSET + 210) * 2, event.getX(0));
+ ASSERT_EQ((Y_OFFSET + 211) * 2, event.getY(0));
+ ASSERT_EQ(212, event.getPressure(0));
ASSERT_EQ(213, event.getSize(0));
- ASSERT_EQ(223, event.getSize(1));
-
- ASSERT_EQ(14, event.getHistoricalTouchMajor(0, 0));
- ASSERT_EQ(24, event.getHistoricalTouchMajor(1, 0));
- ASSERT_EQ(114, event.getHistoricalTouchMajor(0, 1));
- ASSERT_EQ(124, event.getHistoricalTouchMajor(1, 1));
- ASSERT_EQ(214, event.getTouchMajor(0));
- ASSERT_EQ(224, event.getTouchMajor(1));
-
- ASSERT_EQ(15, event.getHistoricalTouchMinor(0, 0));
- ASSERT_EQ(25, event.getHistoricalTouchMinor(1, 0));
- ASSERT_EQ(115, event.getHistoricalTouchMinor(0, 1));
- ASSERT_EQ(125, event.getHistoricalTouchMinor(1, 1));
- ASSERT_EQ(215, event.getTouchMinor(0));
- ASSERT_EQ(225, event.getTouchMinor(1));
-
- ASSERT_EQ(16, event.getHistoricalToolMajor(0, 0));
- ASSERT_EQ(26, event.getHistoricalToolMajor(1, 0));
- ASSERT_EQ(116, event.getHistoricalToolMajor(0, 1));
- ASSERT_EQ(126, event.getHistoricalToolMajor(1, 1));
- ASSERT_EQ(216, event.getToolMajor(0));
- ASSERT_EQ(226, event.getToolMajor(1));
-
- ASSERT_EQ(17, event.getHistoricalToolMinor(0, 0));
- ASSERT_EQ(27, event.getHistoricalToolMinor(1, 0));
- ASSERT_EQ(117, event.getHistoricalToolMinor(0, 1));
- ASSERT_EQ(127, event.getHistoricalToolMinor(1, 1));
- ASSERT_EQ(217, event.getToolMinor(0));
- ASSERT_EQ(227, event.getToolMinor(1));
-
- ASSERT_EQ(18, event.getHistoricalOrientation(0, 0));
- ASSERT_EQ(28, event.getHistoricalOrientation(1, 0));
- ASSERT_EQ(118, event.getHistoricalOrientation(0, 1));
- ASSERT_EQ(128, event.getHistoricalOrientation(1, 1));
+ ASSERT_EQ(214 * 2, event.getTouchMajor(0));
+ ASSERT_EQ(215 * 2, event.getTouchMinor(0));
+ ASSERT_EQ(216 * 2, event.getToolMajor(0));
+ ASSERT_EQ(217 * 2, event.getToolMinor(0));
ASSERT_EQ(218, event.getOrientation(0));
- ASSERT_EQ(228, event.getOrientation(1));
+}
+
+TEST_F(MotionEventTest, Parcel) {
+ Parcel parcel;
+
+ MotionEvent inEvent;
+ initializeEventWithHistory(&inEvent);
+ MotionEvent outEvent;
+
+ // Round trip.
+ inEvent.writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+ outEvent.readFromParcel(&parcel);
+
+ ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
+}
+
+TEST_F(MotionEventTest, Transform) {
+ // Generate some points on a circle.
+ // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle
+ // of ARC * i degrees clockwise relative to the Y axis.
+ // The geometrical representation is irrelevant to the test, it's just easy to generate
+ // and check rotation. We set the orientation to the same angle.
+ // Coordinate system: down is increasing Y, right is increasing X.
+ const float PI_180 = float(M_PI / 180);
+ const float RADIUS = 10;
+ const float ARC = 36;
+ const float ROTATION = ARC * 2;
+
+ const size_t pointerCount = 11;
+ int pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ float angle = float(i * ARC * PI_180);
+ pointerIds[i] = i;
+ pointerCoords[i].clear();
+ pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3);
+ pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2);
+ pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
+ }
+ MotionEvent event;
+ event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ float originalRawX = 0 + 3;
+ float originalRawY = -RADIUS + 2;
+
+ // Check original raw X and Y assumption.
+ ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
+ ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
+
+ // Now translate the motion event so the circle's origin is at (0,0).
+ event.offsetLocation(-3, -2);
+
+ // Offsetting the location should preserve the raw X and Y of the first point.
+ ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
+ ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
+
+ // Apply a rotation about the origin by ROTATION degrees clockwise.
+ SkMatrix matrix;
+ matrix.setRotate(ROTATION);
+ event.transform(&matrix);
+
+ // Check the points.
+ for (size_t i = 0; i < pointerCount; i++) {
+ float angle = float((i * ARC + ROTATION) * PI_180);
+ ASSERT_NEAR(sinf(angle) * RADIUS, event.getX(i), 0.001);
+ ASSERT_NEAR(-cosf(angle) * RADIUS, event.getY(i), 0.001);
+ ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1);
+ }
+
+ // Applying the transformation should preserve the raw X and Y of the first point.
+ ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
+ ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
}
} // namespace android
diff --git a/native/include/android/input.h b/native/include/android/input.h
index ee05020..d531489 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -322,6 +322,7 @@ enum {
/*
* Constants that identify each individual axis of a motion event.
+ * Refer to the documentation on the MotionEvent class for descriptions of each axis.
*/
enum {
AMOTION_EVENT_AXIS_X = 0,
@@ -333,6 +334,35 @@ enum {
AMOTION_EVENT_AXIS_TOOL_MAJOR = 6,
AMOTION_EVENT_AXIS_TOOL_MINOR = 7,
AMOTION_EVENT_AXIS_ORIENTATION = 8,
+ AMOTION_EVENT_AXIS_VSCROLL = 9,
+ AMOTION_EVENT_AXIS_HSCROLL = 10,
+ AMOTION_EVENT_AXIS_Z = 11,
+ AMOTION_EVENT_AXIS_RX = 12,
+ AMOTION_EVENT_AXIS_RY = 13,
+ AMOTION_EVENT_AXIS_RZ = 14,
+ AMOTION_EVENT_AXIS_HAT_X = 15,
+ AMOTION_EVENT_AXIS_HAT_Y = 16,
+ AMOTION_EVENT_AXIS_LTRIGGER = 17,
+ AMOTION_EVENT_AXIS_RTRIGGER = 18,
+ AMOTION_EVENT_AXIS_GENERIC_1 = 32,
+ AMOTION_EVENT_AXIS_GENERIC_2 = 33,
+ AMOTION_EVENT_AXIS_GENERIC_3 = 34,
+ AMOTION_EVENT_AXIS_GENERIC_4 = 35,
+ AMOTION_EVENT_AXIS_GENERIC_5 = 36,
+ AMOTION_EVENT_AXIS_GENERIC_6 = 37,
+ AMOTION_EVENT_AXIS_GENERIC_7 = 38,
+ AMOTION_EVENT_AXIS_GENERIC_8 = 39,
+ AMOTION_EVENT_AXIS_GENERIC_9 = 40,
+ AMOTION_EVENT_AXIS_GENERIC_10 = 41,
+ AMOTION_EVENT_AXIS_GENERIC_11 = 42,
+ AMOTION_EVENT_AXIS_GENERIC_12 = 43,
+ AMOTION_EVENT_AXIS_GENERIC_13 = 44,
+ AMOTION_EVENT_AXIS_GENERIC_14 = 45,
+ AMOTION_EVENT_AXIS_GENERIC_15 = 46,
+ AMOTION_EVENT_AXIS_GENERIC_16 = 47,
+
+ // NOTE: If you add a new axis here you must also add it to several other files.
+ // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
};
/*
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 066daa8..c921425 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -117,6 +117,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
+import android.view.KeyCharacterMap.FallbackAction;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.media.IAudioService;
@@ -1453,7 +1454,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
// Check for fallback actions.
- if (kcm.getFallbackAction(keyCode, metaState, mFallbackAction)) {
+ if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
if (DEBUG_FALLBACK) {
Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
+ " metaState=" + Integer.toHexString(mFallbackAction.metaState));
@@ -1485,6 +1486,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return null;
}
+ private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
+ FallbackAction outFallbackAction) {
+ // Consult the key character map for specific fallback actions.
+ // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
+ if (kcm.getFallbackAction(keyCode, metaState, outFallbackAction)) {
+ return true;
+ }
+ return false;
+ }
+
/**
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 38a896f..f79d106 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -127,9 +127,7 @@ EventHub::EventHub(void) :
mOpened(false), mNeedToSendFinishedDeviceScan(false),
mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-#ifdef EV_SW
memset(mSwitches, 0, sizeof(mSwitches));
-#endif
}
EventHub::~EventHub(void) {
@@ -229,7 +227,7 @@ int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
}
Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
+ device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
@@ -253,7 +251,6 @@ int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
}
int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
-#ifdef EV_SW
if (sw >= 0 && sw <= SW_MAX) {
AutoMutex _l(mLock);
@@ -262,7 +259,6 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
return getSwitchStateLocked(device, sw);
}
}
-#endif
return AKEY_STATE_UNKNOWN;
}
@@ -297,7 +293,8 @@ bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
scanCodes.clear();
- status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
+ status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(
+ keyCodes[codeIndex], &scanCodes);
if (! err) {
// check the possible scan codes identified by the layout map against the
// map of codes actually emitted by the driver
@@ -312,14 +309,14 @@ bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
return true;
}
-status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
+status_t EventHub::mapKey(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const
{
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
+ status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags);
if (err == NO_ERROR) {
return NO_ERROR;
}
@@ -329,7 +326,7 @@ status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
device = getDeviceLocked(mBuiltInKeyboardId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
+ status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags);
if (err == NO_ERROR) {
return NO_ERROR;
}
@@ -341,6 +338,34 @@ status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
return NAME_NOT_FOUND;
}
+status_t EventHub::mapAxis(int32_t deviceId, int scancode,
+ int32_t* outAxis) const
+{
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+
+ if (device && device->keyMap.haveKeyLayout()) {
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ if (err == NO_ERROR) {
+ return NO_ERROR;
+ }
+ }
+
+ if (mBuiltInKeyboardId != -1) {
+ device = getDeviceLocked(mBuiltInKeyboardId);
+
+ if (device && device->keyMap.haveKeyLayout()) {
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ if (err == NO_ERROR) {
+ return NO_ERROR;
+ }
+ }
+ }
+
+ *outAxis = -1;
+ return NAME_NOT_FOUND;
+}
+
void EventHub::addExcludedDevice(const char* deviceName)
{
AutoMutex _l(mLock);
@@ -488,7 +513,7 @@ bool EventHub::getEvent(RawEvent* outEvent) {
if (iev.type == EV_KEY) {
outEvent->keyCode = AKEYCODE_UNKNOWN;
if (device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->map(iev.code,
+ status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code,
&outEvent->keyCode, &outEvent->flags);
LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
iev.code, outEvent->keyCode, outEvent->flags, err);
@@ -731,86 +756,79 @@ int EventHub::openDevice(const char *devicePath) {
loadConfiguration(device);
// Figure out the kinds of events the device reports.
-
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
+ ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
- LOGV("Getting keys...");
- if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
- //LOGI("MAP\n");
- //for (int i = 0; i < sizeof(key_bitmask); i++) {
- // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
- //}
-
- // See if this is a keyboard. Ignore everything in the button range except for
- // joystick and gamepad buttons which are also considered keyboards.
- if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK),
- sizeof_bit_array(BTN_DIGI))
- || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1))) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+ uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
+ memset(abs_bitmask, 0, sizeof(abs_bitmask));
+ ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
- device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
- if (device->keyBitmask != NULL) {
- memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
- } else {
- delete device;
- LOGE("out of memory allocating key bitmask");
- return -1;
- }
+ uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
+ memset(rel_bitmask, 0, sizeof(rel_bitmask));
+ ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
+
+ uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
+ memset(sw_bitmask, 0, sizeof(sw_bitmask));
+ ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask);
+
+ // See if this is a keyboard. Ignore everything in the button range except for
+ // joystick and gamepad buttons which are handled like keyboards for the most part.
+ bool haveKeyboardKeys = containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
+ || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
+ sizeof_bit_array(KEY_MAX + 1));
+ bool haveGamepadButtons =containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_JOYSTICK),
+ sizeof_bit_array(BTN_DIGI));
+ if (haveKeyboardKeys || haveGamepadButtons) {
+ device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+ device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
+ if (device->keyBitmask != NULL) {
+ memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
+ } else {
+ delete device;
+ LOGE("out of memory allocating key bitmask");
+ return -1;
}
}
-
+
// See if this is a cursor device such as a trackball or mouse.
- if (test_bit(BTN_MOUSE, key_bitmask)) {
- uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
- memset(rel_bitmask, 0, sizeof(rel_bitmask));
- LOGV("Getting relative controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
- if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_CURSOR;
- }
- }
+ if (test_bit(BTN_MOUSE, key_bitmask)
+ && test_bit(REL_X, rel_bitmask)
+ && test_bit(REL_Y, rel_bitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
// See if this is a touch pad.
- uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
- memset(abs_bitmask, 0, sizeof(abs_bitmask));
- LOGV("Getting absolute controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
- // Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
- && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+ // Is this a new modern multi-touch driver?
+ if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
+ && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+ // Some joysticks such as the PS3 controller report axes that conflict
+ // with the ABS_MT range. Try to confirm that the device really is
+ // a touch screen.
+ if (test_bit(BTN_TOUCH, key_bitmask) || !haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
-
- // Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, key_bitmask)
- && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH;
}
+ // Is this an old style single-touch driver?
+ } else if (test_bit(BTN_TOUCH, key_bitmask)
+ && test_bit(ABS_X, abs_bitmask)
+ && test_bit(ABS_Y, abs_bitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_TOUCH;
}
-#ifdef EV_SW
// figure out the switches this device reports
- uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
- memset(sw_bitmask, 0, sizeof(sw_bitmask));
- bool hasSwitches = false;
- if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
- for (int i=0; i<EV_SW; i++) {
- //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
- if (test_bit(i, sw_bitmask)) {
- hasSwitches = true;
- if (mSwitches[i] == 0) {
- mSwitches[i] = device->id;
- }
+ bool haveSwitches = false;
+ for (int i=0; i<EV_SW; i++) {
+ //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
+ if (test_bit(i, sw_bitmask)) {
+ haveSwitches = true;
+ if (mSwitches[i] == 0) {
+ mSwitches[i] = device->id;
}
}
}
- if (hasSwitches) {
+ if (haveSwitches) {
device->classes |= INPUT_DEVICE_CLASS_SWITCH;
}
-#endif
if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
// Load the virtual keys for the touch screen, if any.
@@ -862,12 +880,10 @@ int EventHub::openDevice(const char *devicePath) {
// See if this device is a joystick.
// Ignore touchscreens because they use the same absolute axes for other purposes.
+ // Assumes that joysticks always have buttons and the keymap has been loaded.
if (device->classes & INPUT_DEVICE_CLASS_GAMEPAD
&& !(device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
- if (test_bit(ABS_X, abs_bitmask)
- || test_bit(ABS_Y, abs_bitmask)
- || test_bit(ABS_HAT0X, abs_bitmask)
- || test_bit(ABS_HAT0Y, abs_bitmask)) {
+ if (containsNonZeroByte(abs_bitmask, 0, sizeof_bit_array(ABS_MAX + 1))) {
device->classes |= INPUT_DEVICE_CLASS_JOYSTICK;
}
}
@@ -950,7 +966,7 @@ bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
}
Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
+ device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
const size_t N = scanCodes.size();
for (size_t i=0; i<N && i<=KEY_MAX; i++) {
int32_t sc = scanCodes.itemAt(i);
@@ -972,13 +988,11 @@ int EventHub::closeDevice(const char *devicePath) {
device->path.string(), device->identifier.name.string(), device->id,
device->fd, device->classes);
-#ifdef EV_SW
for (int j=0; j<EV_SW; j++) {
if (mSwitches[j] == device->id) {
mSwitches[j] = 0;
}
}
-#endif
if (device->id == mBuiltInKeyboardId) {
LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 52993f7..35712f5 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -167,9 +167,12 @@ public:
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const = 0;
- virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ virtual status_t mapKey(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const = 0;
+ virtual status_t mapAxis(int32_t deviceId, int scancode,
+ int32_t* outAxis) const = 0;
+
// exclude a particular device from opening
// this can be used to ignore input devices for sensors
virtual void addExcludedDevice(const char* deviceName) = 0;
@@ -221,9 +224,12 @@ public:
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const;
- virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ virtual status_t mapKey(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const;
+ virtual status_t mapAxis(int32_t deviceId, int scancode,
+ int32_t* outAxis) const;
+
virtual void addExcludedDevice(const char* deviceName);
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
@@ -314,9 +320,7 @@ private:
List<String8> mExcludedDevices;
// device ids that report particular switches.
-#ifdef EV_SW
int32_t mSwitches[SW_MAX + 1];
-#endif
static const int INPUT_BUFFER_SIZE = 64;
struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 8f38cb2..47cfa05 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -584,15 +584,15 @@ void InputDevice::dump(String8& dump) {
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
if (!deviceInfo.getMotionRanges().isEmpty()) {
dump.append(INDENT2 "Motion Ranges:\n");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
- dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_X, "X");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_Y, "Y");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_PRESSURE, "Pressure");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_SIZE, "Size");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOUCH_MAJOR, "TouchMajor");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOUCH_MINOR, "TouchMinor");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOOL_MAJOR, "ToolMajor");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOOL_MINOR, "ToolMinor");
+ dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_ORIENTATION, "Orientation");
}
size_t numMappers = mMappers.size();
@@ -1061,14 +1061,21 @@ void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
if (mParameters.mode == Parameters::MODE_POINTER) {
float minX, minY, maxX, maxY;
if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
}
} else {
- info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
+ info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
+ info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
+ }
+ info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
+
+ if (mHaveVWheel) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
+ }
+ if (mHaveHWheel) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
}
- info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
}
void CursorInputMapper::dump(String8& dump) {
@@ -1076,8 +1083,14 @@ void CursorInputMapper::dump(String8& dump) {
AutoMutex _l(mLock);
dump.append(INDENT2 "Cursor Input Mapper:\n");
dumpParameters(dump);
+ dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
+ dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
+ dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
+ dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
+ dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
+ dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
} // release lock
@@ -1107,6 +1120,9 @@ void CursorInputMapper::configure() {
mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
break;
}
+
+ mVWheelScale = 1.0f;
+ mHWheelScale = 1.0f;
}
void CursorInputMapper::configureParameters() {
@@ -1200,6 +1216,14 @@ void CursorInputMapper::process(const RawEvent* rawEvent) {
mAccumulator.fields |= Accumulator::FIELD_REL_Y;
mAccumulator.relY = rawEvent->value;
break;
+ case REL_WHEEL:
+ mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
+ mAccumulator.relWheel = rawEvent->value;
+ break;
+ case REL_HWHEEL:
+ mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
+ mAccumulator.relHWheel = rawEvent->value;
+ break;
}
break;
@@ -1302,6 +1326,13 @@ void CursorInputMapper::sync(nsecs_t when) {
}
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
+
+ if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, mAccumulator.relWheel);
+ }
+ if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, mAccumulator.relHWheel);
+ }
} // release lock
int32_t metaState = mContext->getGlobalMetaState();
@@ -1350,35 +1381,35 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
// noticed immediately.
configureSurfaceLocked();
- info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
- info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
+ info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
+ info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
if (mLocked.orientedRanges.havePressure) {
- info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
+ info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
mLocked.orientedRanges.pressure);
}
if (mLocked.orientedRanges.haveSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
+ info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
mLocked.orientedRanges.size);
}
if (mLocked.orientedRanges.haveTouchSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
+ info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
mLocked.orientedRanges.touchMajor);
- info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
+ info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
mLocked.orientedRanges.touchMinor);
}
if (mLocked.orientedRanges.haveToolSize) {
- info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
+ info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
mLocked.orientedRanges.toolMajor);
- info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
+ info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
mLocked.orientedRanges.toolMinor);
}
if (mLocked.orientedRanges.haveOrientation) {
- info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
+ info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
mLocked.orientedRanges.orientation);
}
} // release lock
@@ -1803,7 +1834,7 @@ void TouchInputMapper::configureVirtualKeysLocked() {
virtualKey.scanCode = virtualKeyDefinition.scanCode;
int32_t keyCode;
uint32_t flags;
- if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
+ if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
& keyCode, & flags)) {
LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
virtualKey.scanCode);
@@ -3715,7 +3746,6 @@ void MultiTouchInputMapper::configureRawAxes() {
JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
InputMapper(device) {
- initialize();
}
JoystickInputMapper::~JoystickInputMapper() {
@@ -3728,176 +3758,219 @@ uint32_t JoystickInputMapper::getSources() {
void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
- if (mAxes.x.valid) {
- info->addMotionRange(AINPUT_MOTION_RANGE_X,
- mAxes.x.min, mAxes.x.max, mAxes.x.flat, mAxes.x.fuzz);
- }
- if (mAxes.y.valid) {
- info->addMotionRange(AINPUT_MOTION_RANGE_Y,
- mAxes.y.min, mAxes.y.max, mAxes.y.flat, mAxes.y.fuzz);
+ for (size_t i = 0; i < mAxes.size(); i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
}
}
void JoystickInputMapper::dump(String8& dump) {
dump.append(INDENT2 "Joystick Input Mapper:\n");
- dump.append(INDENT3 "Raw Axes:\n");
- dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
- dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
-
- dump.append(INDENT3 "Normalized Axes:\n");
- dumpNormalizedAxis(dump, mAxes.x, "X");
- dumpNormalizedAxis(dump, mAxes.y, "Y");
- dumpNormalizedAxis(dump, mAxes.hat0X, "Hat0X");
- dumpNormalizedAxis(dump, mAxes.hat0Y, "Hat0Y");
-}
-
-void JoystickInputMapper::dumpNormalizedAxis(String8& dump,
- const NormalizedAxis& axis, const char* name) {
- if (axis.valid) {
+ dump.append(INDENT3 "Axes:\n");
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ const char* label = getAxisLabel(axis.axis);
+ char name[32];
+ if (label) {
+ strncpy(name, label, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ } else {
+ snprintf(name, sizeof(name), "%d", axis.axis);
+ }
dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
- "scale=%0.3f, center=%0.3f, precision=%0.3f, value=%0.3f\n",
+ "scale=%0.3f, offset=%0.3f\n",
name, axis.min, axis.max, axis.flat, axis.fuzz,
- axis.scale, axis.center, axis.precision, axis.value);
- } else {
- dump.appendFormat(INDENT4 "%s: unknown range\n", name);
+ axis.scale, axis.offset);
+ dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
+ mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
+ axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
}
}
void JoystickInputMapper::configure() {
InputMapper::configure();
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0X, & mRawAxes.hat0X);
- getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0Y, & mRawAxes.hat0Y);
+ // Collect all axes.
+ for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
+ RawAbsoluteAxisInfo rawAxisInfo;
+ getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
+ if (rawAxisInfo.valid) {
+ int32_t axisId;
+ bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
+ if (!explicitlyMapped) {
+ // Axis is not explicitly mapped, will choose a generic axis later.
+ axisId = -1;
+ }
+
+ Axis axis;
+ if (isCenteredAxis(axisId)) {
+ float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
+ axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
+ scale, offset, -1.0f, 1.0f,
+ rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
+ } else {
+ float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
+ scale, 0.0f, 0.0f, 1.0f,
+ rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
+ }
+
+ // To eliminate noise while the joystick is at rest, filter out small variations
+ // in axis values up front.
+ axis.filter = axis.flat * 0.25f;
+
+ mAxes.add(abs, axis);
+ }
+ }
+
+ // If there are too many axes, start dropping them.
+ // Prefer to keep explicitly mapped axes.
+ if (mAxes.size() > PointerCoords::MAX_AXES) {
+ LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
+ getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
+ pruneAxes(true);
+ pruneAxes(false);
+ }
- mAxes.x.configure(mRawAxes.x);
- mAxes.y.configure(mRawAxes.y);
- mAxes.hat0X.configure(mRawAxes.hat0X);
- mAxes.hat0Y.configure(mRawAxes.hat0Y);
+ // Assign generic axis ids to remaining axes.
+ int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ if (axis.axis < 0) {
+ while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
+ && haveAxis(nextGenericAxisId)) {
+ nextGenericAxisId += 1;
+ }
+
+ if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
+ axis.axis = nextGenericAxisId;
+ nextGenericAxisId += 1;
+ } else {
+ LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
+ "have already been assigned to other axes.",
+ getDeviceName().string(), mAxes.keyAt(i));
+ mAxes.removeItemsAt(i--);
+ numAxes -= 1;
+ }
+ }
+ }
}
-void JoystickInputMapper::initialize() {
- mAccumulator.clear();
+bool JoystickInputMapper::haveAxis(int32_t axis) {
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ if (mAxes.valueAt(i).axis == axis) {
+ return true;
+ }
+ }
+ return false;
+}
- mAxes.x.resetState();
- mAxes.y.resetState();
- mAxes.hat0X.resetState();
- mAxes.hat0Y.resetState();
+void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
+ size_t i = mAxes.size();
+ while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
+ if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
+ continue;
+ }
+ LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
+ getDeviceName().string(), mAxes.keyAt(i));
+ mAxes.removeItemsAt(i);
+ }
+}
+
+bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
+ switch (axis) {
+ case AMOTION_EVENT_AXIS_X:
+ case AMOTION_EVENT_AXIS_Y:
+ case AMOTION_EVENT_AXIS_Z:
+ case AMOTION_EVENT_AXIS_RX:
+ case AMOTION_EVENT_AXIS_RY:
+ case AMOTION_EVENT_AXIS_RZ:
+ case AMOTION_EVENT_AXIS_HAT_X:
+ case AMOTION_EVENT_AXIS_HAT_Y:
+ case AMOTION_EVENT_AXIS_ORIENTATION:
+ return true;
+ default:
+ return false;
+ }
}
void JoystickInputMapper::reset() {
// Recenter all axes.
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mAccumulator.clear();
- mAccumulator.fields = Accumulator::FIELD_ALL;
- sync(when);
- // Reinitialize state.
- initialize();
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ axis.newValue = 0;
+ }
+
+ sync(when, true /*force*/);
InputMapper::reset();
}
void JoystickInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
- case EV_ABS:
- switch (rawEvent->scanCode) {
- case ABS_X:
- mAccumulator.fields |= Accumulator::FIELD_ABS_X;
- mAccumulator.absX = rawEvent->value;
- break;
- case ABS_Y:
- mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
- mAccumulator.absY = rawEvent->value;
- break;
- case ABS_HAT0X:
- mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0X;
- mAccumulator.absHat0X = rawEvent->value;
- break;
- case ABS_HAT0Y:
- mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0Y;
- mAccumulator.absHat0Y = rawEvent->value;
- break;
+ case EV_ABS: {
+ ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
+ if (index >= 0) {
+ Axis& axis = mAxes.editValueAt(index);
+ float newValue = rawEvent->value * axis.scale + axis.offset;
+ if (newValue != axis.newValue) {
+ axis.newValue = newValue;
+ }
}
break;
+ }
case EV_SYN:
switch (rawEvent->scanCode) {
case SYN_REPORT:
- sync(rawEvent->when);
+ sync(rawEvent->when, false /*force*/);
break;
}
break;
}
}
-void JoystickInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
+void JoystickInputMapper::sync(nsecs_t when, bool force) {
+ if (!force && !haveAxesChangedSignificantly()) {
+ return;
}
int32_t metaState = mContext->getGlobalMetaState();
- bool motionAxisChanged = false;
- if (fields & Accumulator::FIELD_ABS_X) {
- if (mAxes.x.updateValue(mAccumulator.absX)) {
- motionAxisChanged = true;
- }
- }
-
- if (fields & Accumulator::FIELD_ABS_Y) {
- if (mAxes.y.updateValue(mAccumulator.absY)) {
- motionAxisChanged = true;
- }
- }
-
- if (motionAxisChanged) {
- PointerCoords pointerCoords;
- pointerCoords.clear();
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, mAxes.x.value);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, mAxes.y.value);
-
- int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerId, &pointerCoords, mAxes.x.precision, mAxes.y.precision, 0);
- }
-
- if (fields & Accumulator::FIELD_ABS_HAT0X) {
- if (mAxes.hat0X.updateValueAndDirection(mAccumulator.absHat0X)) {
- notifyDirectionalAxis(mAxes.hat0X, when, metaState,
- AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT);
- }
- }
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
- if (fields & Accumulator::FIELD_ABS_HAT0Y) {
- if (mAxes.hat0Y.updateValueAndDirection(mAccumulator.absHat0Y)) {
- notifyDirectionalAxis(mAxes.hat0Y, when, metaState,
- AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN);
- }
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ Axis& axis = mAxes.editValueAt(i);
+ pointerCoords.setAxisValue(axis.axis, axis.newValue);
+ axis.oldValue = axis.newValue;
}
- mAccumulator.clear();
+ int32_t pointerId = 0;
+ getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
+ AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerId, &pointerCoords, 0, 0, 0);
}
-void JoystickInputMapper::notifyDirectionalAxis(DirectionalAxis& axis,
- nsecs_t when, int32_t metaState, int32_t lowKeyCode, int32_t highKeyCode) {
- if (axis.lastKeyCode) {
- getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
- AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM,
- axis.lastKeyCode, 0, metaState, when);
- axis.lastKeyCode = 0;
- }
- if (axis.direction) {
- axis.lastKeyCode = axis.direction > 0 ? highKeyCode : lowKeyCode;
- getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
- AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM,
- axis.lastKeyCode, 0, metaState, when);
+bool JoystickInputMapper::haveAxesChangedSignificantly() {
+ size_t numAxes = mAxes.size();
+ for (size_t i = 0; i < numAxes; i++) {
+ const Axis& axis = mAxes.valueAt(i);
+ if (axis.newValue != axis.oldValue
+ && fabs(axis.newValue - axis.oldValue) > axis.filter) {
+ return true;
+ }
}
+ return false;
}
-
} // namespace android
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 27cb8e1..cf41535 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -481,7 +481,9 @@ private:
enum {
FIELD_BTN_MOUSE = 1,
FIELD_REL_X = 2,
- FIELD_REL_Y = 4
+ FIELD_REL_Y = 4,
+ FIELD_REL_WHEEL = 8,
+ FIELD_REL_HWHEEL = 16,
};
uint32_t fields;
@@ -489,6 +491,8 @@ private:
bool btnMouse;
int32_t relX;
int32_t relY;
+ int32_t relWheel;
+ int32_t relHWheel;
inline void clear() {
fields = 0;
@@ -500,6 +504,12 @@ private:
float mYScale;
float mXPrecision;
float mYPrecision;
+
+ bool mHaveVWheel;
+ bool mHaveHWheel;
+ float mVWheelScale;
+ float mHWheelScale;
+
sp<PointerControllerInterface> mPointerController;
struct LockedState {
@@ -985,123 +995,53 @@ public:
virtual void process(const RawEvent* rawEvent);
private:
- struct RawAxes {
- RawAbsoluteAxisInfo x;
- RawAbsoluteAxisInfo y;
- RawAbsoluteAxisInfo hat0X;
- RawAbsoluteAxisInfo hat0Y;
- } mRawAxes;
-
- struct NormalizedAxis {
- bool valid;
-
- static const float min = -1.0f;
- static const float max = -1.0f;
-
- float scale; // scale factor
- float center; // center offset after scaling
- float precision; // precision
- float flat; // size of flat region
- float fuzz; // error tolerance
-
- float value; // most recent value
-
- NormalizedAxis() : valid(false), scale(0), center(0), precision(0),
- flat(0), fuzz(0), value(0) {
- }
-
- void configure(const RawAbsoluteAxisInfo& rawAxis) {
- if (rawAxis.valid && rawAxis.getRange() != 0) {
- valid = true;
- scale = 2.0f / rawAxis.getRange();
- precision = rawAxis.getRange();
- flat = rawAxis.flat * scale;
- fuzz = rawAxis.fuzz * scale;
- center = float(rawAxis.minValue + rawAxis.maxValue) / rawAxis.getRange();
- }
- }
-
- void resetState() {
- value = 0;
- }
-
- bool updateValue(int32_t rawValue) {
- float newValue = rawValue * scale - center;
- if (value == newValue) {
- return false;
- }
- value = newValue;
- return true;
- }
- };
-
- struct DirectionalAxis : NormalizedAxis {
- int32_t direction; // most recent direction vector: value is one of -1, 0, 1.
-
- int32_t lastKeyCode; // most recent key code produced
-
- DirectionalAxis() : lastKeyCode(0) {
- }
-
- void resetState() {
- NormalizedAxis::resetState();
- direction = 0;
- lastKeyCode = 0;
- }
-
- bool updateValueAndDirection(int32_t rawValue) {
- if (!updateValue(rawValue)) {
- return false;
- }
- if (value > flat) {
- direction = 1;
- } else if (value < -flat) {
- direction = -1;
- } else {
- direction = 0;
- }
- return true;
+ struct Axis {
+ RawAbsoluteAxisInfo rawAxisInfo;
+
+ int32_t axis; // axis id
+ bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
+
+ float scale; // scale factor from raw to normalized values
+ float offset; // offset to add after scaling for normalization
+
+ float min; // normalized inclusive minimum
+ float max; // normalized inclusive maximum
+ float flat; // normalized flat region size
+ float fuzz; // normalized error tolerance
+
+ float oldValue; // previous value
+ float newValue; // most recent value
+
+ float filter; // filter out small variations of this size
+
+ void initialize(const RawAbsoluteAxisInfo& rawAxisInfo,
+ int32_t axis, bool explicitlyMapped, float scale, float offset,
+ float min, float max, float flat, float fuzz) {
+ this->rawAxisInfo = rawAxisInfo;
+ this->axis = axis;
+ this->explicitlyMapped = explicitlyMapped;
+ this->scale = scale;
+ this->offset = offset;
+ this->min = min;
+ this->max = max;
+ this->flat = flat;
+ this->fuzz = fuzz;
+ this->filter = 0;
+ this->oldValue = 0;
+ this->newValue = 0;
}
};
- struct Axes {
- NormalizedAxis x;
- NormalizedAxis y;
- DirectionalAxis hat0X;
- DirectionalAxis hat0Y;
- } mAxes;
-
- struct Accumulator {
- enum {
- FIELD_ABS_X = 1,
- FIELD_ABS_Y = 2,
- FIELD_ABS_HAT0X = 4,
- FIELD_ABS_HAT0Y = 8,
-
- FIELD_ALL = FIELD_ABS_X | FIELD_ABS_Y | FIELD_ABS_HAT0X | FIELD_ABS_HAT0Y,
- };
-
- uint32_t fields;
-
- int32_t absX;
- int32_t absY;
- int32_t absHat0X;
- int32_t absHat0Y;
-
- inline void clear() {
- fields = 0;
- }
- } mAccumulator;
+ // Axes indexed by raw ABS_* axis index.
+ KeyedVector<int32_t, Axis> mAxes;
- void initialize();
-
- void sync(nsecs_t when);
+ void sync(nsecs_t when, bool force);
- void notifyDirectionalAxis(DirectionalAxis& axis,
- nsecs_t when, int32_t metaState, int32_t lowKeyCode, int32_t highKeyCode);
+ bool haveAxis(int32_t axis);
+ void pruneAxes(bool ignoreExplicitlyMappedAxes);
+ bool haveAxesChangedSignificantly();
- static void dumpNormalizedAxis(String8& dump,
- const NormalizedAxis& axis, const char* name);
+ static bool isCenteredAxis(int32_t axis);
};
} // namespace android
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 41d67ed..648250e 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -561,7 +561,7 @@ private:
return -1;
}
- virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ virtual status_t mapKey(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const {
Device* device = getDevice(deviceId);
if (device) {
@@ -579,6 +579,11 @@ private:
return NAME_NOT_FOUND;
}
+ virtual status_t mapAxis(int32_t deviceId, int scancode,
+ int32_t* outAxis) const {
+ return NAME_NOT_FOUND;
+ }
+
virtual void addExcludedDevice(const char* deviceName) {
mExcludedDevices.add(String8(deviceName));
}
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 097b109..8ab9b6a 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -17,6 +17,7 @@
#include <ui/KeyCharacterMap.h>
#include <ui/KeyLayoutMap.h>
#include <ui/VirtualKeyMap.h>
+#include <utils/PropertyMap.h>
#include <utils/String8.h>
#include <stdio.h>
@@ -32,6 +33,7 @@ enum FileType {
FILETYPE_KEYLAYOUT,
FILETYPE_KEYCHARACTERMAP,
FILETYPE_VIRTUALKEYDEFINITION,
+ FILETYPE_INPUTDEVICECONFIGURATION,
};
@@ -39,9 +41,9 @@ static void usage() {
fprintf(stderr, "Keymap Validation Tool\n\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr,
- " %s [*.kl] [*.kcm] [virtualkeys.*] [...]\n"
- " Validates the specified key layouts, key character maps \n"
- " or virtual key definitions.\n\n",
+ " %s [*.kl] [*.kcm] [*.idc] [virtualkeys.*] [...]\n"
+ " Validates the specified key layouts, key character maps, \n"
+ " input device configurations, or virtual key definitions.\n\n",
gProgName);
}
@@ -54,6 +56,9 @@ static FileType getFileType(const char* filename) {
if (strcmp(extension, ".kcm") == 0) {
return FILETYPE_KEYCHARACTERMAP;
}
+ if (strcmp(extension, ".idc") == 0) {
+ return FILETYPE_INPUTDEVICECONFIGURATION;
+ }
}
if (strstr(filename, "virtualkeys.")) {
@@ -92,6 +97,16 @@ static bool validateFile(const char* filename) {
break;
}
+ case FILETYPE_INPUTDEVICECONFIGURATION: {
+ PropertyMap* map;
+ status_t status = PropertyMap::load(String8(filename), &map);
+ if (status) {
+ fprintf(stderr, "Error %d parsing input device configuration file.\n\n", status);
+ return false;
+ }
+ break;
+ }
+
case FILETYPE_VIRTUALKEYDEFINITION: {
VirtualKeyMap* map;
status_t status = VirtualKeyMap::load(String8(filename), &map);