summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/input/Input.h11
-rw-r--r--libs/input/Input.cpp29
-rw-r--r--services/inputflinger/InputDispatcher.cpp33
3 files changed, 47 insertions, 26 deletions
diff --git a/include/input/Input.h b/include/input/Input.h
index ea9c4c284..bb5ceaf20 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -22,11 +22,12 @@
*/
#include <android/input.h>
-#include <utils/Vector.h>
+#include <utils/BitSet.h>
#include <utils/KeyedVector.h>
-#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
/*
* Additional private constants not defined in ndk/ui/input.h.
@@ -205,7 +206,11 @@ struct PointerCoords {
float values[MAX_AXES];
inline void clear() {
- bits = 0;
+ BitSet64::clear(bits);
+ }
+
+ bool isEmpty() const {
+ return BitSet64::isEmpty(bits);
}
float getAxisValue(int32_t axis) const;
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index ccbf52b88..d9f22e9d5 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -158,16 +158,10 @@ 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)) {
+ if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
return 0;
}
- uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
- return values[index];
+ return values[BitSet64::getIndexOfBit(bits, axis)];
}
status_t PointerCoords::setAxisValue(int32_t axis, float value) {
@@ -175,22 +169,23 @@ status_t PointerCoords::setAxisValue(int32_t axis, float value) {
return NAME_NOT_FOUND;
}
- uint64_t axisBit = 1LL << axis;
- uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
- if (!(bits & axisBit)) {
+ uint32_t index = BitSet64::getIndexOfBit(bits, axis);
+ if (!BitSet64::hasBit(bits, axis)) {
if (value == 0) {
return OK; // axes with value 0 do not need to be stored
}
- uint32_t count = __builtin_popcountll(bits);
+
+ uint32_t count = BitSet64::count(bits);
if (count >= MAX_AXES) {
tooManyAxes(axis);
return NO_MEMORY;
}
- bits |= axisBit;
+ BitSet64::markBit(bits, axis);
for (uint32_t i = count; i > index; i--) {
values[i] = values[i - 1];
}
}
+
values[index] = value;
return OK;
}
@@ -222,7 +217,7 @@ void PointerCoords::applyOffset(float xOffset, float yOffset) {
status_t PointerCoords::readFromParcel(Parcel* parcel) {
bits = parcel->readInt64();
- uint32_t count = __builtin_popcountll(bits);
+ uint32_t count = BitSet64::count(bits);
if (count > MAX_AXES) {
return BAD_VALUE;
}
@@ -236,7 +231,7 @@ status_t PointerCoords::readFromParcel(Parcel* parcel) {
status_t PointerCoords::writeToParcel(Parcel* parcel) const {
parcel->writeInt64(bits);
- uint32_t count = __builtin_popcountll(bits);
+ uint32_t count = BitSet64::count(bits);
for (uint32_t i = 0; i < count; i++) {
parcel->writeFloat(values[i]);
}
@@ -253,7 +248,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const {
if (bits != other.bits) {
return false;
}
- uint32_t count = __builtin_popcountll(bits);
+ uint32_t count = BitSet64::count(bits);
for (uint32_t i = 0; i < count; i++) {
if (values[i] != other.values[i]) {
return false;
@@ -264,7 +259,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const {
void PointerCoords::copyFrom(const PointerCoords& other) {
bits = other.bits;
- uint32_t count = __builtin_popcountll(bits);
+ uint32_t count = BitSet64::count(bits);
for (uint32_t i = 0; i < count; i++) {
values[i] = other.values[i];
}
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index f933681c4..56044ee9a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -4108,18 +4108,39 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
case AMOTION_EVENT_ACTION_POINTER_UP:
case AMOTION_EVENT_ACTION_POINTER_DOWN:
case AMOTION_EVENT_ACTION_MOVE: {
+ if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
+ // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to
+ // generate cancellation events for these since they're based in relative rather than
+ // absolute units.
+ return true;
+ }
+
ssize_t index = findMotionMemento(entry, false /*hovering*/);
+
+ if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
+ // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
+ // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any
+ // other value and we need to track the motion so we can send cancellation events for
+ // anything generating fallback events (e.g. DPad keys for joystick movements).
+ if (index >= 0) {
+ if (entry->pointerCoords[0].isEmpty()) {
+ mMotionMementos.removeAt(index);
+ } else {
+ MotionMemento& memento = mMotionMementos.editItemAt(index);
+ memento.setPointers(entry);
+ }
+ } else if (!entry->pointerCoords[0].isEmpty()) {
+ addMotionMemento(entry, flags, false /*hovering*/);
+ }
+
+ // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+ return true;
+ }
if (index >= 0) {
MotionMemento& memento = mMotionMementos.editItemAt(index);
memento.setPointers(entry);
return true;
}
- if (actionMasked == AMOTION_EVENT_ACTION_MOVE
- && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
- | AINPUT_SOURCE_CLASS_NAVIGATION))) {
- // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
- return true;
- }
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Dropping inconsistent motion pointer up/down or move event: "
"deviceId=%d, source=%08x, actionMasked=%d",