summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml55
-rw-r--r--core/java/android/view/MotionEvent.java86
-rw-r--r--data/keyboards/Generic.kl6
-rw-r--r--data/keyboards/Vendor_045e_Product_028e.kl46
-rw-r--r--data/keyboards/Vendor_046d_Product_c294.kl53
-rw-r--r--data/keyboards/Vendor_046d_Product_c299.kl62
-rw-r--r--data/keyboards/common.mk3
-rw-r--r--include/ui/KeyLayoutMap.h34
-rwxr-xr-xinclude/ui/KeycodeLabels.h5
-rw-r--r--libs/ui/KeyLayoutMap.cpp97
-rw-r--r--native/include/android/input.h5
-rw-r--r--services/input/EventHub.cpp8
-rw-r--r--services/input/EventHub.h4
-rw-r--r--services/input/InputReader.cpp167
-rw-r--r--services/input/InputReader.h37
-rw-r--r--services/input/tests/InputReader_test.cpp2
16 files changed, 601 insertions, 69 deletions
diff --git a/api/current.xml b/api/current.xml
index 422522e..142ff2b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -218115,6 +218115,28 @@
visibility="public"
>
</field>
+<field name="AXIS_BRAKE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="23"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GAS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="22"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_GENERIC_1"
type="int"
transient="false"
@@ -218368,6 +218390,17 @@
visibility="public"
>
</field>
+<field name="AXIS_RUDDER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_RX"
type="int"
transient="false"
@@ -218412,6 +218445,17 @@
visibility="public"
>
</field>
+<field name="AXIS_THROTTLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="19"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_TOOL_MAJOR"
type="int"
transient="false"
@@ -218467,6 +218511,17 @@
visibility="public"
>
</field>
+<field name="AXIS_WHEEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="21"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_X"
type="int"
transient="false"
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 076f712..3c39149 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -675,6 +675,87 @@ public final class MotionEvent extends InputEvent implements Parcelable {
public static final int AXIS_RTRIGGER = 18;
/**
+ * Constant used to identify the Throttle axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the throttle control.
+ * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_THROTTLE = 19;
+
+ /**
+ * Constant used to identify the Rudder axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the rudder control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn 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_RUDDER = 20;
+
+ /**
+ * Constant used to identify the Wheel axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the steering wheel control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn 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_WHEEL = 21;
+
+ /**
+ * Constant used to identify the Gas axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the gas (accelerator) control.
+ * The value is normalized to a range from 0.0 (no acceleration)
+ * to 1.0 (maximum acceleration).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GAS = 22;
+
+ /**
+ * Constant used to identify the Brake axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the brake control.
+ * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_BRAKE = 23;
+
+ /**
* Constant used to identify the Generic 1 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
@@ -877,6 +958,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {
names.append(AXIS_HAT_Y, "AXIS_HAT_Y");
names.append(AXIS_LTRIGGER, "AXIS_LTRIGGER");
names.append(AXIS_RTRIGGER, "AXIS_RTRIGGER");
+ names.append(AXIS_THROTTLE, "AXIS_THROTTLE");
+ names.append(AXIS_RUDDER, "AXIS_RUDDER");
+ names.append(AXIS_WHEEL, "AXIS_WHEEL");
+ names.append(AXIS_GAS, "AXIS_GAS");
+ names.append(AXIS_BRAKE, "AXIS_BRAKE");
names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1");
names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2");
names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3");
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 6d925d6..1428b63 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -409,6 +409,10 @@ axis 0x02 Z
axis 0x03 RX
axis 0x04 RY
axis 0x05 RZ
+axis 0x06 THROTTLE
+axis 0x07 RUDDER
+axis 0x08 WHEEL
+axis 0x09 GAS
+axis 0x0a BRAKE
axis 0x10 HAT_X
axis 0x11 HAT_Y
- \ No newline at end of file
diff --git a/data/keyboards/Vendor_045e_Product_028e.kl b/data/keyboards/Vendor_045e_Product_028e.kl
new file mode 100644
index 0000000..99f046a
--- /dev/null
+++ b/data/keyboards/Vendor_045e_Product_028e.kl
@@ -0,0 +1,46 @@
+# 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.
+
+#
+# XBox 360 USB Controller
+#
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 314 BUTTON_SELECT
+key 315 BUTTON_START
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+# Left and right stick.
+# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd.
+# This confuses applications that rely on the flat value because the joystick actually
+# settles in a flat range of +/- 4096 or so.
+axis 0x00 X flat 4096
+axis 0x01 Y flat 4096
+axis 0x03 Z flat 4096
+axis 0x04 RZ flat 4096
+
+# Triggers.
+axis 0x02 LTRIGGER
+axis 0x05 RTRIGGER
+
+# Hat.
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
diff --git a/data/keyboards/Vendor_046d_Product_c294.kl b/data/keyboards/Vendor_046d_Product_c294.kl
new file mode 100644
index 0000000..5492f49
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_c294.kl
@@ -0,0 +1,53 @@
+# 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 G25 Racing Wheel (in Compatibility Mode)
+#
+
+# 4 way buttons above hat
+key 0x121 BUTTON_A
+key 0x123 BUTTON_B
+key 0x120 BUTTON_X
+key 0x122 BUTTON_Y
+
+# Row of buttons under hat
+key 0x12b BUTTON_1
+key 0x128 BUTTON_2
+key 0x129 BUTTON_3
+key 0x12a BUTTON_4
+
+# Gear shift positions
+# 0x12a top-left gear (aliased as BUTTON_4)
+# 0x12b bottom-left gear (aliased as BUTTON_1)
+
+# Buttons on wheel
+key 0x127 BUTTON_L1
+key 0x126 BUTTON_R1
+
+# Toggles under wheel
+key 0x125 BUTTON_L2
+key 0x124 BUTTON_R2
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Steering Wheel
+axis 0x00 WHEEL
+
+# Accelerator / Brake
+# 00..7e : accelerator
+# 80..ff : brake
+axis 0x01 split 0x7f GAS BRAKE
diff --git a/data/keyboards/Vendor_046d_Product_c299.kl b/data/keyboards/Vendor_046d_Product_c299.kl
new file mode 100644
index 0000000..d42963d
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_c299.kl
@@ -0,0 +1,62 @@
+# 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 G25 Racing Wheel (in Native Mode)
+#
+
+# 4 way buttons above hat
+key 0x121 BUTTON_A
+key 0x123 BUTTON_B
+key 0x120 BUTTON_X
+key 0x122 BUTTON_Y
+
+# Row of buttons under hat
+key 0x12b BUTTON_1
+key 0x128 BUTTON_2
+key 0x129 BUTTON_3
+key 0x12a BUTTON_4
+
+# Gear shift positions
+key 0x12c BUTTON_5
+key 0x12d BUTTON_6
+key 0x12e BUTTON_7
+key 0x12f BUTTON_8
+key 0x2d0 BUTTON_9
+key 0x2d1 BUTTON_10
+key 0x2d2 BUTTON_11
+
+# Buttons on wheel
+key 0x127 BUTTON_L1
+key 0x126 BUTTON_R1
+
+# Toggles under wheel
+key 0x125 BUTTON_L2
+key 0x124 BUTTON_R2
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Steering Wheel
+axis 0x00 WHEEL
+
+# Clutch
+axis 0x01 invert GENERIC_1
+
+# Accelerator
+axis 0x02 invert GAS
+
+# Brake
+axis 0x05 invert BRAKE
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
index 5b367b9..335298c 100644
--- a/data/keyboards/common.mk
+++ b/data/keyboards/common.mk
@@ -19,7 +19,10 @@ keylayouts := \
Generic.kl \
AVRCP.kl \
qwerty.kl \
+ Vendor_045e_Product_028e.kl \
Vendor_046d_Product_c216.kl \
+ Vendor_046d_Product_c294.kl \
+ Vendor_046d_Product_c299.kl \
Vendor_046d_Product_c532.kl \
Vendor_054c_Product_0268.kl \
Vendor_05ac_Product_0239.kl \
diff --git a/include/ui/KeyLayoutMap.h b/include/ui/KeyLayoutMap.h
index 904c8f3..d82d0c8 100644
--- a/include/ui/KeyLayoutMap.h
+++ b/include/ui/KeyLayoutMap.h
@@ -24,6 +24,36 @@
namespace android {
+struct AxisInfo {
+ enum Mode {
+ // Axis value is reported directly.
+ MODE_NORMAL = 0,
+ // Axis value should be inverted before reporting.
+ MODE_INVERT = 1,
+ // Axis value should be split into two axes
+ MODE_SPLIT = 2,
+ };
+
+ // Axis mode.
+ Mode mode;
+
+ // Axis id.
+ // When split, this is the axis used for values smaller than the split position.
+ int32_t axis;
+
+ // When split, this is the axis used for values after higher than the split position.
+ int32_t highAxis;
+
+ // The split value, or 0 if not split.
+ int32_t splitValue;
+
+ // The flat value, or -1 if none.
+ int32_t flatOverride;
+
+ AxisInfo() : mode(MODE_NORMAL), axis(-1), highAxis(-1), splitValue(0), flatOverride(-1) {
+ }
+};
+
/**
* Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes.
*/
@@ -36,7 +66,7 @@ public:
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;
+ status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;
private:
struct Key {
@@ -45,7 +75,7 @@ private:
};
KeyedVector<int32_t, Key> mKeys;
- KeyedVector<int32_t, int32_t> mAxes;
+ KeyedVector<int32_t, AxisInfo> mAxes;
KeyLayoutMap();
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index bdfbf7c..b912e9b 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -270,6 +270,11 @@ static const KeycodeLabel AXES[] = {
{ "HAT_Y", 16 },
{ "LTRIGGER", 17 },
{ "RTRIGGER", 18 },
+ { "THROTTLE", 19 },
+ { "RUDDER", 20 },
+ { "WHEEL", 21 },
+ { "GAS", 22 },
+ { "BRAKE", 23 },
{ "GENERIC_1", 32 },
{ "GENERIC_2", 33 },
{ "GENERIC_3", 34 },
diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp
index 2ed0e66..8626a03 100644
--- a/libs/ui/KeyLayoutMap.cpp
+++ b/libs/ui/KeyLayoutMap.cpp
@@ -113,20 +113,23 @@ status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* out
return NO_ERROR;
}
-status_t KeyLayoutMap::mapAxis(int32_t scanCode, int32_t* axis) const {
+status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) 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);
+ *outAxisInfo = mAxes.valueAt(index);
#if DEBUG_MAPPING
- LOGD("mapAxis: scanCode=%d ~ Result axis=%d.", scanCode, *axis);
+ LOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, "
+ "splitValue=%d, flatOverride=%d.",
+ scanCode,
+ outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis,
+ outAxisInfo->splitValue, outAxisInfo->flatOverride);
#endif
return NO_ERROR;
}
@@ -249,19 +252,89 @@ status_t KeyLayoutMap::Parser::parseAxis() {
return BAD_VALUE;
}
+ AxisInfo axisInfo;
+
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;
+ String8 token = mTokenizer->nextToken(WHITESPACE);
+ if (token == "invert") {
+ axisInfo.mode = AxisInfo::MODE_INVERT;
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 axisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.axis = getAxisByLabel(axisToken.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected inverted axis label, got '%s'.",
+ mTokenizer->getLocation().string(), axisToken.string());
+ return BAD_VALUE;
+ }
+ } else if (token == "split") {
+ axisInfo.mode = AxisInfo::MODE_SPLIT;
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 splitToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0));
+ if (*end) {
+ LOGE("%s: Expected split value, got '%s'.",
+ mTokenizer->getLocation().string(), splitToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.axis = getAxisByLabel(lowAxisToken.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected low axis label, got '%s'.",
+ mTokenizer->getLocation().string(), lowAxisToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.highAxis = getAxisByLabel(highAxisToken.string());
+ if (axisInfo.highAxis < 0) {
+ LOGE("%s: Expected high axis label, got '%s'.",
+ mTokenizer->getLocation().string(), highAxisToken.string());
+ return BAD_VALUE;
+ }
+ } else {
+ axisInfo.axis = getAxisByLabel(token.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
+ mTokenizer->getLocation().string(), token.string());
+ return BAD_VALUE;
+ }
+ }
+
+ for (;;) {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ if (mTokenizer->isEol()) {
+ break;
+ }
+ String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
+ if (keywordToken == "flat") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 flatToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0));
+ if (*end) {
+ LOGE("%s: Expected flat value, got '%s'.",
+ mTokenizer->getLocation().string(), flatToken.string());
+ return BAD_VALUE;
+ }
+ } else {
+ LOGE("%s: Expected keyword 'flat', got '%s'.",
+ mTokenizer->getLocation().string(), keywordToken.string());
+ return BAD_VALUE;
+ }
}
#if DEBUG_PARSER
- LOGD("Parsed axis: scanCode=%d, axis=%d.", scanCode, axis);
+ LOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
+ "splitValue=%d, flatOverride=%d.",
+ scanCode,
+ axisInfo.mode, axisInfo.axis, axisInfo.highAxis,
+ axisInfo.splitValue, axisInfo.flatOverride);
#endif
- mMap->mAxes.add(scanCode, axis);
+ mMap->mAxes.add(scanCode, axisInfo);
return NO_ERROR;
}
diff --git a/native/include/android/input.h b/native/include/android/input.h
index f19e8be..86be54a 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -359,6 +359,11 @@ enum {
AMOTION_EVENT_AXIS_HAT_Y = 16,
AMOTION_EVENT_AXIS_LTRIGGER = 17,
AMOTION_EVENT_AXIS_RTRIGGER = 18,
+ AMOTION_EVENT_AXIS_THROTTLE = 19,
+ AMOTION_EVENT_AXIS_RUDDER = 20,
+ AMOTION_EVENT_AXIS_WHEEL = 21,
+ AMOTION_EVENT_AXIS_GAS = 22,
+ AMOTION_EVENT_AXIS_BRAKE = 23,
AMOTION_EVENT_AXIS_GENERIC_1 = 32,
AMOTION_EVENT_AXIS_GENERIC_2 = 33,
AMOTION_EVENT_AXIS_GENERIC_3 = 34,
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 2fe5980..e37a6b1 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -352,14 +352,13 @@ status_t EventHub::mapKey(int32_t deviceId, int scancode,
return NAME_NOT_FOUND;
}
-status_t EventHub::mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const
+status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo) const
{
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo);
if (err == NO_ERROR) {
return NO_ERROR;
}
@@ -369,14 +368,13 @@ status_t EventHub::mapAxis(int32_t deviceId, int scancode,
device = getDeviceLocked(mBuiltInKeyboardId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo);
if (err == NO_ERROR) {
return NO_ERROR;
}
}
}
- *outAxis = -1;
return NAME_NOT_FOUND;
}
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 445c04b..ab42a1f 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -176,7 +176,7 @@ public:
int32_t* outKeycode, uint32_t* outFlags) const = 0;
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const = 0;
+ AxisInfo* outAxisInfo) const = 0;
// exclude a particular device from opening
// this can be used to ignore input devices for sensors
@@ -235,7 +235,7 @@ public:
int32_t* outKeycode, uint32_t* outFlags) const;
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const;
+ AxisInfo* outAxisInfo) const;
virtual void addExcludedDevice(const char* deviceName);
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index b92c3b5..00c3eb7 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -3854,7 +3854,10 @@ void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
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);
+ info->addMotionRange(axis.axisInfo.axis, axis.min, axis.max, axis.flat, axis.fuzz);
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ info->addMotionRange(axis.axisInfo.highAxis, axis.min, axis.max, axis.flat, axis.fuzz);
+ }
}
}
@@ -3865,18 +3868,29 @@ void JoystickInputMapper::dump(String8& dump) {
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];
+ const char* label = getAxisLabel(axis.axisInfo.axis);
if (label) {
- strncpy(name, label, sizeof(name));
- name[sizeof(name) - 1] = '\0';
+ dump.appendFormat(INDENT4 "%s", label);
} else {
- snprintf(name, sizeof(name), "%d", axis.axis);
+ dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
+ }
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ label = getAxisLabel(axis.axisInfo.highAxis);
+ if (label) {
+ dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
+ } else {
+ dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
+ axis.axisInfo.splitValue);
+ }
+ } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
+ dump.append(" (invert)");
}
- dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
- "scale=%0.3f, offset=%0.3f\n",
- name, axis.min, axis.max, axis.flat, axis.fuzz,
- axis.scale, axis.offset);
+
+ dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
+ axis.min, axis.max, axis.flat, axis.fuzz);
+ dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
+ "highScale=%0.5f, highOffset=%0.5f\n",
+ axis.scale, axis.offset, axis.highScale, axis.highOffset);
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);
@@ -3891,25 +3905,38 @@ void JoystickInputMapper::configure() {
RawAbsoluteAxisInfo rawAxisInfo;
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
if (rawAxisInfo.valid) {
- int32_t axisId;
- bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
+ // Map axis.
+ AxisInfo axisInfo;
+ bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
if (!explicitlyMapped) {
// Axis is not explicitly mapped, will choose a generic axis later.
- axisId = -1;
+ axisInfo.mode = AxisInfo::MODE_NORMAL;
+ axisInfo.axis = -1;
}
+ // Apply flat override.
+ int32_t rawFlat = axisInfo.flatOverride < 0
+ ? rawAxisInfo.flat : axisInfo.flatOverride;
+
+ // Calculate scaling factors and limits.
Axis axis;
- if (isCenteredAxis(axisId)) {
+ if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
+ float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, 0.0f, highScale, 0.0f,
+ 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
+ } else if (isCenteredAxis(axisInfo.axis)) {
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);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, offset, scale, offset,
+ -1.0f, 1.0f, rawFlat * 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);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, 0.0f, scale, 0.0f,
+ 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
}
// To eliminate noise while the joystick is at rest, filter out small variations
@@ -3934,14 +3961,14 @@ void JoystickInputMapper::configure() {
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
Axis& axis = mAxes.editValueAt(i);
- if (axis.axis < 0) {
+ if (axis.axisInfo.axis < 0) {
while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
&& haveAxis(nextGenericAxisId)) {
nextGenericAxisId += 1;
}
if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
- axis.axis = nextGenericAxisId;
+ axis.axisInfo.axis = nextGenericAxisId;
nextGenericAxisId += 1;
} else {
LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
@@ -3954,10 +3981,13 @@ void JoystickInputMapper::configure() {
}
}
-bool JoystickInputMapper::haveAxis(int32_t axis) {
+bool JoystickInputMapper::haveAxis(int32_t axisId) {
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
- if (mAxes.valueAt(i).axis == axis) {
+ const Axis& axis = mAxes.valueAt(i);
+ if (axis.axisInfo.axis == axisId
+ || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
+ && axis.axisInfo.highAxis == axisId)) {
return true;
}
}
@@ -3987,6 +4017,8 @@ bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
case AMOTION_EVENT_AXIS_HAT_X:
case AMOTION_EVENT_AXIS_HAT_Y:
case AMOTION_EVENT_AXIS_ORIENTATION:
+ case AMOTION_EVENT_AXIS_RUDDER:
+ case AMOTION_EVENT_AXIS_WHEEL:
return true;
default:
return false;
@@ -4000,7 +4032,7 @@ void JoystickInputMapper::reset() {
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
Axis& axis = mAxes.editValueAt(i);
- axis.newValue = 0;
+ axis.resetValue();
}
sync(when, true /*force*/);
@@ -4014,10 +4046,34 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) {
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;
+ float newValue, highNewValue;
+ switch (axis.axisInfo.mode) {
+ case AxisInfo::MODE_INVERT:
+ newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
+ * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ break;
+ case AxisInfo::MODE_SPLIT:
+ if (rawEvent->value < axis.axisInfo.splitValue) {
+ newValue = (axis.axisInfo.splitValue - rawEvent->value)
+ * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ } else if (rawEvent->value > axis.axisInfo.splitValue) {
+ newValue = 0.0f;
+ highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
+ * axis.highScale + axis.highOffset;
+ } else {
+ newValue = 0.0f;
+ highNewValue = 0.0f;
+ }
+ break;
+ default:
+ newValue = rawEvent->value * axis.scale + axis.offset;
+ highNewValue = 0.0f;
+ break;
}
+ axis.newValue = newValue;
+ axis.highNewValue = highNewValue;
}
break;
}
@@ -4033,7 +4089,7 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) {
}
void JoystickInputMapper::sync(nsecs_t when, bool force) {
- if (!force && !haveAxesChangedSignificantly()) {
+ if (!filterAxes(force)) {
return;
}
@@ -4044,9 +4100,11 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) {
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;
+ const Axis& axis = mAxes.valueAt(i);
+ pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
+ }
}
// Moving a joystick axis should not wake the devide because joysticks can
@@ -4061,12 +4119,49 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) {
1, &pointerId, &pointerCoords, 0, 0, 0);
}
-bool JoystickInputMapper::haveAxesChangedSignificantly() {
+bool JoystickInputMapper::filterAxes(bool force) {
+ bool atLeastOneSignificantChange = force;
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) {
+ Axis& axis = mAxes.editValueAt(i);
+ if (force || hasValueChangedSignificantly(axis.filter,
+ axis.newValue, axis.currentValue, axis.min, axis.max)) {
+ axis.currentValue = axis.newValue;
+ atLeastOneSignificantChange = true;
+ }
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ if (force || hasValueChangedSignificantly(axis.filter,
+ axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
+ axis.highCurrentValue = axis.highNewValue;
+ atLeastOneSignificantChange = true;
+ }
+ }
+ }
+ return atLeastOneSignificantChange;
+}
+
+bool JoystickInputMapper::hasValueChangedSignificantly(
+ float filter, float newValue, float currentValue, float min, float max) {
+ if (newValue != currentValue) {
+ // Filter out small changes in value unless the value is converging on the axis
+ // bounds or center point. This is intended to reduce the amount of information
+ // sent to applications by particularly noisy joysticks (such as PS3).
+ if (fabs(newValue - currentValue) > filter
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
+ || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
+ float filter, float newValue, float currentValue, float thresholdValue) {
+ float newDistance = fabs(newValue - thresholdValue);
+ if (newDistance < filter) {
+ float oldDistance = fabs(currentValue - thresholdValue);
+ if (newDistance < oldDistance) {
return true;
}
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 655f0f0..e2cf08e 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1011,38 +1011,50 @@ public:
private:
struct Axis {
RawAbsoluteAxisInfo rawAxisInfo;
+ AxisInfo axisInfo;
- 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 highScale; // scale factor from raw to normalized values of high split
+ float highOffset; // offset to add after scaling for normalization of high split
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
+ float currentValue; // current value
+ float newValue; // most recent value
+ float highCurrentValue; // current value of high split
+ float highNewValue; // most recent value of high split
- void initialize(const RawAbsoluteAxisInfo& rawAxisInfo,
- int32_t axis, bool explicitlyMapped, float scale, float offset,
+ void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
+ bool explicitlyMapped, float scale, float offset,
+ float highScale, float highOffset,
float min, float max, float flat, float fuzz) {
this->rawAxisInfo = rawAxisInfo;
- this->axis = axis;
+ this->axisInfo = axisInfo;
this->explicitlyMapped = explicitlyMapped;
this->scale = scale;
this->offset = offset;
+ this->highScale = highScale;
+ this->highOffset = highOffset;
this->min = min;
this->max = max;
this->flat = flat;
this->fuzz = fuzz;
this->filter = 0;
- this->oldValue = 0;
+ resetValue();
+ }
+
+ void resetValue() {
+ this->currentValue = 0;
this->newValue = 0;
+ this->highCurrentValue = 0;
+ this->highNewValue = 0;
}
};
@@ -1051,9 +1063,14 @@ private:
void sync(nsecs_t when, bool force);
- bool haveAxis(int32_t axis);
+ bool haveAxis(int32_t axisId);
void pruneAxes(bool ignoreExplicitlyMappedAxes);
- bool haveAxesChangedSignificantly();
+ bool filterAxes(bool force);
+
+ static bool hasValueChangedSignificantly(float filter,
+ float newValue, float currentValue, float min, float max);
+ static bool hasMovedNearerToValueWithinFilteredRange(float filter,
+ float newValue, float currentValue, float thresholdValue);
static bool isCenteredAxis(int32_t axis);
};
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 8404b3a..d77cb2f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -592,7 +592,7 @@ private:
}
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const {
+ AxisInfo* outAxisInfo) const {
return NAME_NOT_FOUND;
}