diff --git a/api/current.xml b/api/current.xml
index f65b5ce270fce..c4cac831508af 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -145940,6 +145940,19 @@
visibility="public"
>
+
+
+
+
-
+
@@ -146059,7 +146072,7 @@
deprecated="not deprecated"
visibility="public"
>
-
+
@@ -146087,7 +146100,7 @@
deprecated="not deprecated"
visibility="public"
>
-
+
@@ -146115,7 +146128,7 @@
deprecated="not deprecated"
visibility="public"
>
-
+
@@ -146153,6 +146166,19 @@
visibility="public"
>
+
+
+
+
-
+
-
+
-
+
-
+
-
-not an index into the array of pointer values,
+ * which is compacted to only contain pointers that are down; the pointer
+ * ID for a particular index can be found with {@link #findPointerIndex}.
*/
- public static final int ACTION_POINTER_MASK = 0xff00;
+ public static final int ACTION_POINTER_ID_MASK = 0xff00;
/**
* Bit shift for the action bits holding the pointer identifier as
- * defined by {@link #ACTION_POINTER_MASK}.
+ * defined by {@link #ACTION_POINTER_ID_MASK}.
*/
- public static final int ACTION_POINTER_SHIFT = 8;
+ public static final int ACTION_POINTER_ID_SHIFT = 8;
private static final boolean TRACK_RECYCLED_LOCATION = false;
@@ -143,18 +155,6 @@ public final class MotionEvent implements Parcelable {
*/
public static final int EDGE_RIGHT = 0x00000008;
- /**
- * This is the part of the state data that holds the finger identifier
- * for the sample.
- */
- static private final int STATE_FINGER_ID_MASK = 0xff;
-
- /**
- * Special value for STATE_FINGER_ID_MASK indicating that the finger
- * is not down in that sample.
- */
- static private final int STATE_FINGER_ID_NONE = 0xff;
-
/**
* Offset for the sample's X coordinate.
* @hide
@@ -212,8 +212,8 @@ public final class MotionEvent implements Parcelable {
private int mNumPointers;
private int mNumSamples;
- // Array of (mNumSamples * mNumPointers) size of control data.
- private int[] mStateSamples;
+ // Array of mNumPointers size of identifiers for each pointer of data.
+ private int[] mPointerIdentifiers;
// Array of (mNumSamples * mNumPointers * NUM_SAMPLE_DATA) size of event data.
private float[] mDataSamples;
// Array of mNumSamples size of time stamps.
@@ -224,7 +224,7 @@ public final class MotionEvent implements Parcelable {
private boolean mRecycled;
private MotionEvent() {
- mStateSamples = new int[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES];
+ mPointerIdentifiers = new int[BASE_AVAIL_POINTERS];
mDataSamples = new float[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES*NUM_SAMPLE_DATA];
mTimeSamples = new long[BASE_AVAIL_SAMPLES];
}
@@ -256,16 +256,11 @@ public final class MotionEvent implements Parcelable {
* @param action The kind of action being performed -- one of either
* {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
* {@link #ACTION_CANCEL}.
- * @param x The X coordinate of this event.
- * @param y The Y coordinate of this event.
- * @param pressure The current pressure of this event. The pressure generally
- * ranges from 0 (no pressure at all) to 1 (normal pressure), however
- * values higher than 1 may be generated depending on the calibration of
- * the input device.
- * @param size A scaled value of the approximate size of the area being pressed when
- * touched with the finger. The actual value in pixels corresponding to the finger
- * touch is normalized with a device specific range of values
- * and scaled to a value between 0 and 1.
+ * @param pointers The number of points that will be in this event.
+ * @param inPointerIds An array of pointers values providing
+ * an identifier for each pointer.
+ * @param inData An array of pointers*NUM_SAMPLE_DATA of initial
+ * data samples for the event.
* @param metaState The state of any meta / modifier keys that were in effect when
* the event was generated.
* @param xPrecision The precision of the X coordinate being reported.
@@ -279,7 +274,7 @@ public final class MotionEvent implements Parcelable {
* @hide
*/
static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
- int action, int pointers, float[] inData, int metaState,
+ int action, int pointers, int[] inPointerIds, float[] inData, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
MotionEvent ev = obtain();
ev.mDeviceId = deviceId;
@@ -295,17 +290,25 @@ public final class MotionEvent implements Parcelable {
ev.mNumPointers = pointers;
ev.mNumSamples = 1;
- float[] data = ev.mDataSamples;
- System.arraycopy(inData, 0, data, 0, pointers * NUM_SAMPLE_DATA);
-
- int[] state = ev.mStateSamples;
- while (pointers > 0) {
- pointers--;
- state[pointers] = pointers;
- }
-
+ System.arraycopy(inPointerIds, 0, ev.mPointerIdentifiers, 0, pointers);
+ System.arraycopy(inData, 0, ev.mDataSamples, 0, pointers * NUM_SAMPLE_DATA);
ev.mTimeSamples[0] = eventTime;
+ if (DEBUG_POINTERS) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("New:");
+ for (int i=0; i= NT) {
- System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NT);
+ final int NS = ev.mNumSamples = o.mNumSamples;
+ if (ev.mTimeSamples.length >= NS) {
+ System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NS);
} else {
ev.mTimeSamples = (long[])o.mTimeSamples.clone();
}
- final int NS = (ev.mNumPointers=o.mNumPointers) * NT;
- if (ev.mStateSamples.length >= NS) {
- System.arraycopy(o.mStateSamples, 0, ev.mStateSamples, 0, NS);
+ final int NP = (ev.mNumPointers=o.mNumPointers);
+ if (ev.mPointerIdentifiers.length >= NP) {
+ System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
} else {
- ev.mStateSamples = (int[])o.mStateSamples.clone();
+ ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
}
- final int ND = NS * NUM_SAMPLE_DATA;
+ final int ND = NP * NS * NUM_SAMPLE_DATA;
if (ev.mDataSamples.length >= ND) {
System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
} else {
@@ -592,6 +595,38 @@ public final class MotionEvent implements Parcelable {
return mEventTimeNano;
}
+ /**
+ * {@link #getX(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
+ */
+ public final float getX() {
+ return mDataSamples[SAMPLE_X];
+ }
+
+ /**
+ * {@link #getY(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
+ */
+ public final float getY() {
+ return mDataSamples[SAMPLE_Y];
+ }
+
+ /**
+ * {@link #getPressure(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
+ */
+ public final float getPressure() {
+ return mDataSamples[SAMPLE_PRESSURE];
+ }
+
+ /**
+ * {@link #getSize(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
+ */
+ public final float getSize() {
+ return mDataSamples[SAMPLE_SIZE];
+ }
+
/**
* The number of pointers of data contained in this event. Always
* >= 1.
@@ -601,80 +636,91 @@ public final class MotionEvent implements Parcelable {
}
/**
- * {@link #getX(int)} for the first pointer (pointer 0).
+ * Return the pointer identifier associated with a particular pointer
+ * data index is this event. The identifier tells you the actual pointer
+ * number associated with the data, accounting for individual pointers
+ * going up and down since the start of the current gesture.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
- public final float getX() {
- return mDataSamples[SAMPLE_X];
+ public final int getPointerId(int index) {
+ return mPointerIdentifiers[index];
}
-
+
/**
- * {@link #getY(int)} for the first pointer (pointer 0).
+ * Given a pointer identifier, find the index of its data in the event.
+ *
+ * @param pointerId The identifier of the pointer to be found.
+ * @return Returns either the index of the pointer (for use with
+ * {@link #getX(int) et al.), or -1 if there is no data available for
+ * that pointer identifier.
*/
- public final float getY() {
- return mDataSamples[SAMPLE_Y];
+ public final int findPointerIndex(int pointerId) {
+ int i = mNumPointers;
+ while (i > 0) {
+ i--;
+ if (mPointerIdentifiers[i] == pointerId) {
+ return i;
+ }
+ }
+ return -1;
}
-
+
/**
- * {@link #getPressure(int)} for the first pointer (pointer 0).
- */
- public final float getPressure() {
- return mDataSamples[SAMPLE_PRESSURE];
- }
-
- /**
- * {@link #getSize(int)} for the first pointer (pointer 0).
- */
- public final float getSize() {
- return mDataSamples[SAMPLE_SIZE];
- }
-
- /**
- * Returns the X coordinate of this event for the given pointer.
+ * Returns the X coordinate of this event for the given pointer
+ * index (use {@link #getPointerId(int)} to find the pointer
+ * identifier for this index).
* Whole numbers are pixels; the
* value may have a fraction for input devices that are sub-pixel precise.
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
- public final float getX(int pointer) {
- return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_X];
+ public final float getX(int pointerIndex) {
+ return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_X];
}
/**
- * Returns the Y coordinate of this event for the given pointer.
+ * Returns the Y coordinate of this event for the given pointer
+ * index (use {@link #getPointerId(int)} to find the pointer
+ * identifier for this index).
* Whole numbers are pixels; the
* value may have a fraction for input devices that are sub-pixel precise.
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
- public final float getY(int pointer) {
- return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_Y];
+ public final float getY(int pointerIndex) {
+ return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_Y];
}
/**
- * Returns the current pressure of this event for the given pointer.
+ * Returns the current pressure of this event for the given pointer
+ * index (use {@link #getPointerId(int)} to find the pointer
+ * identifier for this index).
* The pressure generally
* ranges from 0 (no pressure at all) to 1 (normal pressure), however
* values higher than 1 may be generated depending on the calibration of
* the input device.
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
- public final float getPressure(int pointer) {
- return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
+ public final float getPressure(int pointerIndex) {
+ return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
}
/**
- * Returns a scaled value of the approximate size for the given pointer,
- * representing the area of the screen being pressed.
- * The actual value in pixels corresponding to the
+ * Returns a scaled value of the approximate size for the given pointer
+ * index (use {@link #getPointerId(int)} to find the pointer
+ * identifier for this index).
+ * This 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.
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
- public final float getSize(int pointer) {
- return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
+ public final float getSize(int pointerIndex) {
+ return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
}
/**
@@ -758,99 +804,107 @@ public final class MotionEvent implements Parcelable {
}
/**
- * {@link #getHistoricalX(int)} for the first pointer (pointer 0).
+ * {@link #getHistoricalX(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
*/
public final float getHistoricalX(int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_X];
}
/**
- * {@link #getHistoricalY(int)} for the first pointer (pointer 0).
+ * {@link #getHistoricalY(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
*/
public final float getHistoricalY(int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_Y];
}
/**
- * {@link #getHistoricalPressure(int)} for the first pointer (pointer 0).
+ * {@link #getHistoricalPressure(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
*/
public final float getHistoricalPressure(int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_PRESSURE];
}
/**
- * {@link #getHistoricalSize(int)} for the first pointer (pointer 0).
+ * {@link #getHistoricalSize(int)} for the first pointer index (may be an
+ * arbitrary pointer identifier).
*/
public final float getHistoricalSize(int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_SIZE];
}
/**
- * Returns a historical X coordinate that occurred between this event
- * and the previous event for the given pointer. Only applies to ACTION_MOVE events.
+ * Returns a historical X coordinate, as per {@link #getX(int)}, that
+ * occurred between this event and the previous event for the given pointer.
+ * Only applies to ACTION_MOVE events.
*
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
* @param pos Which historical value to return; must be less than
* {@link #getHistorySize}
*
* @see #getHistorySize
* @see #getX
*/
- public final float getHistoricalX(int pointer, int pos) {
+ public final float getHistoricalX(int pointerIndex, int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointer * NUM_SAMPLE_DATA) + SAMPLE_X];
+ + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_X];
}
/**
- * Returns a historical Y coordinate that occurred between this event
- * and the previous event for the given pointer. Only applies to ACTION_MOVE events.
+ * Returns a historical Y coordinate, as per {@link #getY(int)}, that
+ * occurred between this event and the previous event for the given pointer.
+ * Only applies to ACTION_MOVE events.
*
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
* @param pos Which historical value to return; must be less than
* {@link #getHistorySize}
*
* @see #getHistorySize
* @see #getY
*/
- public final float getHistoricalY(int pointer, int pos) {
+ public final float getHistoricalY(int pointerIndex, int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointer * NUM_SAMPLE_DATA) + SAMPLE_Y];
+ + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_Y];
}
/**
- * Returns a historical pressure coordinate that occurred between this event
- * and the previous event for the given pointer. Only applies to ACTION_MOVE events.
+ * Returns a historical pressure coordinate, as per {@link #getPressure(int)},
+ * that occurred between this event and the previous event for the given
+ * pointer. Only applies to ACTION_MOVE events.
*
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
* @param pos Which historical value to return; must be less than
* {@link #getHistorySize}
- *
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ *
* @see #getHistorySize
* @see #getPressure
*/
- public final float getHistoricalPressure(int pointer, int pos) {
+ public final float getHistoricalPressure(int pointerIndex, int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointer * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
+ + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
}
/**
- * Returns a historical size coordinate that occurred between this event
- * and the previous event for the given pointer. Only applies to ACTION_MOVE events.
+ * Returns a historical size coordinate, as per {@link #getSize(int)}, that
+ * occurred between this event and the previous event for the given pointer.
+ * Only applies to ACTION_MOVE events.
*
+ * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
+ * (the first pointer that is down) to {@link #getPointerCount()}-1.
* @param pos Which historical value to return; must be less than
* {@link #getHistorySize}
- *
- * @param pointer The desired pointer to retrieve. Value may be from 0
- * (the first pointer) to {@link #getPointerCount()}-1.
+ *
* @see #getHistorySize
* @see #getSize
*/
- public final float getHistoricalSize(int pointer, int pos) {
+ public final float getHistoricalSize(int pointerIndex, int pos) {
return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointer * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
+ + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
}
/**
@@ -938,7 +992,6 @@ public final class MotionEvent implements Parcelable {
*/
public final void addBatch(long eventTime, float x, float y,
float pressure, float size, int metaState) {
- int[] states = mStateSamples;
float[] data = mDataSamples;
long[] times = mTimeSamples;
@@ -946,14 +999,8 @@ public final class MotionEvent implements Parcelable {
final int NS = mNumSamples;
final int NI = NP*NS;
final int ND = NI * NUM_SAMPLE_DATA;
- if (states.length < (NI+NP)) {
- // The state and data arrays are sized together, since their
- // size is always a fixed factor from each other.
- final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
- int[] newState = new int[NEW_NI];
- System.arraycopy(states, 0, newState, 0, NI);
- mStateSamples = states = newState;
- final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
+ if (data.length <= ND) {
+ final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
float[] newData = new float[NEW_ND];
System.arraycopy(data, 0, newData, 0, ND);
mDataSamples = data = newData;
@@ -996,7 +1043,6 @@ public final class MotionEvent implements Parcelable {
* @hide
*/
public final void addBatch(long eventTime, float[] inData, int metaState) {
- int[] states = mStateSamples;
float[] data = mDataSamples;
long[] times = mTimeSamples;
@@ -1004,14 +1050,8 @@ public final class MotionEvent implements Parcelable {
final int NS = mNumSamples;
final int NI = NP*NS;
final int ND = NI * NUM_SAMPLE_DATA;
- if (states.length < (NI+NP)) {
- // The state and data arrays are sized together, since their
- // size is always a fixed factor from each other.
- final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
- int[] newState = new int[NEW_NI];
- System.arraycopy(states, 0, newState, 0, NI);
- mStateSamples = states = newState;
- final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
+ if (data.length <= ND) {
+ final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
float[] newData = new float[NEW_ND];
System.arraycopy(data, 0, newData, 0, ND);
mDataSamples = data = newData;
@@ -1034,6 +1074,21 @@ public final class MotionEvent implements Parcelable {
mRawX = inData[SAMPLE_X];
mRawY = inData[SAMPLE_Y];
mMetaState |= metaState;
+
+ if (DEBUG_POINTERS) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Add:");
+ for (int i=0; i 0) {
int i;
- int[] state = mStateSamples;
- for (i=0; i 0) {
- final int NI4 = NI*4;
- int[] state = mStateSamples;
- if (state.length < NI) {
- mStateSamples = state = new int[NI];
+ int[] ids = mPointerIdentifiers;
+ if (ids.length < NP) {
+ mPointerIdentifiers = ids = new int[NP];
}
- for (int i=0; i
+#include
#include
#include
@@ -58,6 +59,18 @@
#define SEQ_SHIFT 16
#define id_to_index(id) ((id&ID_MASK)+1)
+#ifndef ABS_MT_TOUCH_MAJOR
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#endif
+
+#ifndef ABS_MT_POSITION_X
+#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#endif
+
+#ifndef ABS_MT_POSITION_Y
+#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#endif
+
namespace android {
static const char *WAKE_LOCK_ID = "KeyEvents";
@@ -590,6 +603,8 @@ int EventHub::open_device(const char *deviceName)
mFDs[mFDCount].events = POLLIN;
// figure out the kinds of events the device reports
+
+ // See if this is a keyboard, and classify it.
uint8_t key_bitmask[(KEY_MAX+1)/8];
memset(key_bitmask, 0, sizeof(key_bitmask));
LOGV("Getting keys...");
@@ -601,15 +616,11 @@ int EventHub::open_device(const char *deviceName)
for (int i=0; i<((BTN_MISC+7)/8); i++) {
if (key_bitmask[i] != 0) {
device->classes |= CLASS_KEYBOARD;
- // 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (test_bit(KEY_Q, key_bitmask)) {
- device->classes |= CLASS_ALPHAKEY;
- }
break;
}
}
if ((device->classes & CLASS_KEYBOARD) != 0) {
- device->keyBitmask = new uint8_t[(KEY_MAX+1)/8];
+ device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
if (device->keyBitmask != NULL) {
memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
} else {
@@ -619,6 +630,8 @@ int EventHub::open_device(const char *deviceName)
}
}
}
+
+ // See if this is a trackball.
if (test_bit(BTN_MOUSE, key_bitmask)) {
uint8_t rel_bitmask[(REL_MAX+1)/8];
memset(rel_bitmask, 0, sizeof(rel_bitmask));
@@ -630,16 +643,22 @@ int EventHub::open_device(const char *deviceName)
}
}
}
- if (test_bit(BTN_TOUCH, key_bitmask)) {
- uint8_t abs_bitmask[(ABS_MAX+1)/8];
- memset(abs_bitmask, 0, sizeof(abs_bitmask));
- LOGV("Getting absolute controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0)
- {
- if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
- device->classes |= CLASS_TOUCHSCREEN;
- }
- }
+
+ uint8_t abs_bitmask[(ABS_MAX+1)/8];
+ memset(abs_bitmask, 0, sizeof(abs_bitmask));
+ LOGV("Getting absolute controllers...");
+ ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
+
+ // Is this a new modern multi-touch driver?
+ if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
+ && test_bit(ABS_MT_POSITION_X, abs_bitmask)
+ && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+ device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_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 |= CLASS_TOUCHSCREEN;
}
#ifdef EV_SW
@@ -658,9 +677,6 @@ int EventHub::open_device(const char *deviceName)
}
#endif
- LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
- deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
-
if ((device->classes&CLASS_KEYBOARD) != 0) {
char devname[101];
char tmpfn[101];
@@ -707,10 +723,27 @@ int EventHub::open_device(const char *deviceName)
sprintf(propName, "hw.keyboards.%u.devname", publicID);
property_set(propName, devname);
- LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
+ // 'Q' key support = cheap test of whether this is an alpha-capable kbd
+ if (hasKeycode(device, kKeyCodeQ)) {
+ device->classes |= CLASS_ALPHAKEY;
+ }
+
+ // See if this has a DPAD.
+ if (hasKeycode(device, kKeyCodeDpadUp) &&
+ hasKeycode(device, kKeyCodeDpadDown) &&
+ hasKeycode(device, kKeyCodeDpadLeft) &&
+ hasKeycode(device, kKeyCodeDpadRight) &&
+ hasKeycode(device, kKeyCodeDpadCenter)) {
+ device->classes |= CLASS_DPAD;
+ }
+
+ LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
publicID, device->id, devname, propName, keylayoutFilename);
}
+ LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
+ deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
+
LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
deviceName, device, mFDCount, devid, device->classes);
@@ -723,6 +756,25 @@ int EventHub::open_device(const char *deviceName)
return 0;
}
+bool EventHub::hasKeycode(device_t* device, int keycode) const
+{
+ if (device->keyBitmask == NULL || device->layoutMap == NULL) {
+ return false;
+ }
+
+ Vector scanCodes;
+ device->layoutMap->findScancodes(keycode, &scanCodes);
+ const size_t N = scanCodes.size();
+ for (size_t i=0; i= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
int EventHub::close_device(const char *deviceName)
{
AutoMutex _l(mLock);
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 0ac5740cd0981..cb23c45581435 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -23,11 +23,13 @@ import android.view.Surface;
import android.view.WindowManagerPolicy;
public class InputDevice {
+ static final boolean DEBUG_POINTERS = false;
+
/** Amount that trackball needs to move in order to generate a key event. */
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
/** Maximum number of pointers we will track and report. */
- static final int MAX_POINTERS = 2;
+ static final int MAX_POINTERS = 10;
final int id;
final int classes;
@@ -51,100 +53,316 @@ public class InputDevice {
float yMoveScale;
MotionEvent currentMove = null;
boolean changed = false;
- boolean mLastAnyDown = false;
long mDownTime = 0;
- final boolean[] mLastDown = new boolean[MAX_POINTERS];
- final boolean[] mDown = new boolean[MAX_POINTERS];
+
+ // The currently assigned pointer IDs, corresponding to the last data.
+ int[] mPointerIds = new int[MAX_POINTERS];
+
+ // This is the last generated pointer data, ordered to match
+ // mPointerIds.
+ int mLastNumPointers = 0;
final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
- final int[] mCurData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
+
+ // This is the next set of pointer data being generated. It is not
+ // in any known order, and will be propagated in to mLastData
+ // as part of mapping it to the appropriate pointer IDs.
+ // Note that we have one extra sample of data here, to help clients
+ // avoid doing bounds checking.
+ int mNextNumPointers = 0;
+ final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
+ + MotionEvent.NUM_SAMPLE_DATA];
+
+ // Temporary data structures for doing the pointer ID mapping.
+ final int[] mLast2Next = new int[MAX_POINTERS];
+ final int[] mNext2Last = new int[MAX_POINTERS];
+ final long[] mNext2LastDistance = new long[MAX_POINTERS];
+
+ // Temporary data structure for generating the final motion data.
final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
+ // This is not used here, but can be used by callers for state tracking.
+ int mAddingPointerOffset = 0;
+ final boolean[] mDown = new boolean[MAX_POINTERS];
+
MotionState(int mx, int my) {
xPrecision = mx;
yPrecision = my;
xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
+ for (int i=0; i= 0) {
+ if (DEBUG_POINTERS) Log.v("InputDevice",
+ "Worst new pointer: " + worstJ
+ + " (distance=" + worstDistance + ")");
+ if (assignPointer(worstJ, false)) {
+ // In this case there is no last pointer
+ // remaining for this new one!
+ next2Last[worstJ] = -1;
+ }
+ }
+ } while (numFound > 2);
+ }
+ }
+
+ int retIndex = -1;
+
+ if (lastNumPointers < nextNumPointers) {
+ // We have one or more new pointers that are down. Create a
+ // new pointer identifier for one of them.
+ if (DEBUG_POINTERS) Log.v("InputDevice", "Adding new pointer");
+ int nextId = 0;
+ int i=0;
+ while (i < lastNumPointers) {
+ if (mPointerIds[i] > nextId) {
+ // Found a hole, insert the pointer here.
+ if (DEBUG_POINTERS) Log.v("InputDevice",
+ "Inserting new pointer at hole " + i);
+ System.arraycopy(mPointerIds, i, mPointerIds,
+ i+1, lastNumPointers-i);
+ System.arraycopy(lastData, i*MotionEvent.NUM_SAMPLE_DATA,
+ lastData, (i+1)*MotionEvent.NUM_SAMPLE_DATA,
+ (lastNumPointers-i)*MotionEvent.NUM_SAMPLE_DATA);
+ break;
+ }
+ i++;
+ nextId++;
+ }
+
+ if (DEBUG_POINTERS) Log.v("InputDevice",
+ "New pointer id " + nextId + " at index " + i);
+
+ mLastNumPointers++;
+ retIndex = i;
+ mPointerIds[i] = nextId;
+
+ // And assign this identifier to the first new pointer.
+ for (int j=0; j= 0) {
+ if (DEBUG_POINTERS) Log.v("InputDevice",
+ "Copying next pointer index " + i
+ + " to last index " + lastIndex);
+ System.arraycopy(nextData, i*MotionEvent.NUM_SAMPLE_DATA,
+ lastData, lastIndex*MotionEvent.NUM_SAMPLE_DATA,
+ MotionEvent.NUM_SAMPLE_DATA);
+ }
+ }
+
+ if (lastNumPointers > nextNumPointers) {
+ // One or more pointers has gone up. Find the first one,
+ // and adjust accordingly.
+ if (DEBUG_POINTERS) Log.v("InputDevice", "Removing old pointer");
+ for (int i=0; i= 0 && index < lastNumPointers) {
+ System.arraycopy(mPointerIds, index+1, mPointerIds,
+ index, lastNumPointers-index-1);
+ System.arraycopy(mLastData, (index+1)*MotionEvent.NUM_SAMPLE_DATA,
+ mLastData, (index)*MotionEvent.NUM_SAMPLE_DATA,
+ (lastNumPointers-index-1)*MotionEvent.NUM_SAMPLE_DATA);
+ mLastNumPointers--;
+ }
}
MotionEvent generateAbsMotion(InputDevice device, long curTime,
long curTimeNano, Display display, int orientation,
int metaState) {
- final float[] scaled = mReportData;
- final int[] cur = mCurData;
-
- boolean anyDown = false;
- int firstDownChanged = -1;
- int numPointers = 0;
- for (int i=0; i MAX_POINTERS) {
+ Log.w("InputDevice", "Number of pointers " + mNextNumPointers
+ + " exceeded maximum of " + MAX_POINTERS);
+ mNextNumPointers = MAX_POINTERS;
+ }
+
+ int upOrDownPointer = updatePointerIdentifiers();
+
+ final float[] reportData = mReportData;
+ final int[] rawData = mLastData;
+
+ final int numPointers = mLastNumPointers;
+
+ if (DEBUG_POINTERS) Log.v("InputDevice", "Processing "
+ + numPointers + " pointers (going from " + lastNumPointers
+ + " to " + nextNumPointers + ")");
+
+ for (int i=0; i absX.maxValue
- || cur[MotionEvent.SAMPLE_Y] < absY.minValue
- || cur[MotionEvent.SAMPLE_Y] > absY.maxValue) {
- if (false) Log.v("InputDevice", "Rejecting ("
- + cur[MotionEvent.SAMPLE_X] + ","
- + cur[MotionEvent.SAMPLE_Y] + "): outside of ("
- + absX.minValue + "," + absY.minValue
- + ")-(" + absX.maxValue + ","
- + absY.maxValue + ")");
- return null;
+ if (nextNumPointers != lastNumPointers) {
+ if (nextNumPointers > lastNumPointers) {
+ if (lastNumPointers == 0) {
+ action = MotionEvent.ACTION_DOWN;
+ mDownTime = curTime;
+ } else {
+ action = MotionEvent.ACTION_POINTER_DOWN
+ | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
}
- }
- mLastAnyDown = anyDown;
- if (anyDown) {
- action = MotionEvent.ACTION_DOWN;
- mDownTime = curTime;
} else {
- action = MotionEvent.ACTION_UP;
- }
- currentMove = null;
- } else if (firstDownChanged >= 0) {
- if (mDown[firstDownChanged]) {
- action = MotionEvent.ACTION_POINTER_DOWN
- | (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
- } else {
- action = MotionEvent.ACTION_POINTER_UP
- | (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
+ if (numPointers == 1) {
+ action = MotionEvent.ACTION_UP;
+ } else {
+ action = MotionEvent.ACTION_POINTER_UP
+ | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+ }
}
currentMove = null;
} else {
@@ -170,42 +388,42 @@ public class InputDevice {
final int j = i * MotionEvent.NUM_SAMPLE_DATA;
if (absX != null) {
- scaled[j + MotionEvent.SAMPLE_X] =
- ((scaled[j + MotionEvent.SAMPLE_X]-absX.minValue)
+ reportData[j + MotionEvent.SAMPLE_X] =
+ ((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
/ absX.range) * w;
}
if (absY != null) {
- scaled[j + MotionEvent.SAMPLE_Y] =
- ((scaled[j + MotionEvent.SAMPLE_Y]-absY.minValue)
+ reportData[j + MotionEvent.SAMPLE_Y] =
+ ((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)
/ absY.range) * h;
}
if (absPressure != null) {
- scaled[j + MotionEvent.SAMPLE_PRESSURE] =
- ((scaled[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
+ reportData[j + MotionEvent.SAMPLE_PRESSURE] =
+ ((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
/ (float)absPressure.range);
}
if (absSize != null) {
- scaled[j + MotionEvent.SAMPLE_SIZE] =
- ((scaled[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
+ reportData[j + MotionEvent.SAMPLE_SIZE] =
+ ((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
/ (float)absSize.range);
}
switch (orientation) {
case Surface.ROTATION_90: {
- final float temp = scaled[MotionEvent.SAMPLE_X];
- scaled[j + MotionEvent.SAMPLE_X] = scaled[j + MotionEvent.SAMPLE_Y];
- scaled[j + MotionEvent.SAMPLE_Y] = w-temp;
+ final float temp = reportData[MotionEvent.SAMPLE_X];
+ reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y];
+ reportData[j + MotionEvent.SAMPLE_Y] = w-temp;
break;
}
case Surface.ROTATION_180: {
- scaled[j + MotionEvent.SAMPLE_X] = w-scaled[j + MotionEvent.SAMPLE_X];
- scaled[j + MotionEvent.SAMPLE_Y] = h-scaled[j + MotionEvent.SAMPLE_Y];
+ reportData[j + MotionEvent.SAMPLE_X] = w-reportData[j + MotionEvent.SAMPLE_X];
+ reportData[j + MotionEvent.SAMPLE_Y] = h-reportData[j + MotionEvent.SAMPLE_Y];
break;
}
case Surface.ROTATION_270: {
- final float temp = scaled[i + MotionEvent.SAMPLE_X];
- scaled[j + MotionEvent.SAMPLE_X] = h-scaled[j + MotionEvent.SAMPLE_Y];
- scaled[j + MotionEvent.SAMPLE_Y] = temp;
+ final float temp = reportData[i + MotionEvent.SAMPLE_X];
+ reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y];
+ reportData[j + MotionEvent.SAMPLE_Y] = temp;
break;
}
}
@@ -214,24 +432,24 @@ public class InputDevice {
// We only consider the first pointer when computing the edge
// flags, since they are global to the event.
if (action == MotionEvent.ACTION_DOWN) {
- if (scaled[MotionEvent.SAMPLE_X] <= 0) {
+ if (reportData[MotionEvent.SAMPLE_X] <= 0) {
edgeFlags |= MotionEvent.EDGE_LEFT;
- } else if (scaled[MotionEvent.SAMPLE_X] >= dispW) {
+ } else if (reportData[MotionEvent.SAMPLE_X] >= dispW) {
edgeFlags |= MotionEvent.EDGE_RIGHT;
}
- if (scaled[MotionEvent.SAMPLE_Y] <= 0) {
+ if (reportData[MotionEvent.SAMPLE_Y] <= 0) {
edgeFlags |= MotionEvent.EDGE_TOP;
- } else if (scaled[MotionEvent.SAMPLE_Y] >= dispH) {
+ } else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) {
edgeFlags |= MotionEvent.EDGE_BOTTOM;
}
}
if (currentMove != null) {
if (false) Log.i("InputDevice", "Adding batch x="
- + scaled[MotionEvent.SAMPLE_X]
- + " y=" + scaled[MotionEvent.SAMPLE_Y]
+ + reportData[MotionEvent.SAMPLE_X]
+ + " y=" + reportData[MotionEvent.SAMPLE_Y]
+ " to " + currentMove);
- currentMove.addBatch(curTime, scaled, metaState);
+ currentMove.addBatch(curTime, reportData, metaState);
if (WindowManagerPolicy.WATCH_POINTER) {
Log.i("KeyInputQueue", "Updating: " + currentMove);
}
@@ -239,37 +457,53 @@ public class InputDevice {
}
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
- curTimeNano, action, numPointers, scaled, metaState,
- xPrecision, yPrecision, device.id, edgeFlags);
+ curTimeNano, action, numPointers, mPointerIds, reportData,
+ metaState, xPrecision, yPrecision, device.id, edgeFlags);
if (action == MotionEvent.ACTION_MOVE) {
currentMove = me;
}
+
+ if (nextNumPointers < lastNumPointers) {
+ removeOldPointer(upOrDownPointer);
+ }
+
return me;
}
+ boolean hasMore() {
+ return mLastNumPointers != mNextNumPointers;
+ }
+
+ void finish() {
+ mNextNumPointers = mAddingPointerOffset = 0;
+ mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;
+ }
+
MotionEvent generateRelMotion(InputDevice device, long curTime,
long curTimeNano, int orientation, int metaState) {
final float[] scaled = mReportData;
// For now we only support 1 pointer with relative motions.
- scaled[MotionEvent.SAMPLE_X] = mCurData[MotionEvent.SAMPLE_X];
- scaled[MotionEvent.SAMPLE_Y] = mCurData[MotionEvent.SAMPLE_Y];
+ scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X];
+ scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y];
scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
scaled[MotionEvent.SAMPLE_SIZE] = 0;
int edgeFlags = 0;
int action;
- if (mDown[0] != mLastDown[0]) {
- mCurData[MotionEvent.SAMPLE_X] =
- mCurData[MotionEvent.SAMPLE_Y] = 0;
- mLastDown[0] = mDown[0];
- if (mDown[0]) {
+ if (mNextNumPointers != mLastNumPointers) {
+ mNextData[MotionEvent.SAMPLE_X] =
+ mNextData[MotionEvent.SAMPLE_Y] = 0;
+ if (mNextNumPointers > 0 && mLastNumPointers == 0) {
action = MotionEvent.ACTION_DOWN;
mDownTime = curTime;
- } else {
+ } else if (mNextNumPointers == 0) {
action = MotionEvent.ACTION_UP;
+ } else {
+ action = MotionEvent.ACTION_MOVE;
}
+ mLastNumPointers = mNextNumPointers;
currentMove = null;
} else {
action = MotionEvent.ACTION_MOVE;
@@ -310,7 +544,7 @@ public class InputDevice {
}
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
- curTimeNano, action, 1, scaled, metaState,
+ curTimeNano, action, 1, mPointerIds, scaled, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
if (action == MotionEvent.ACTION_MOVE) {
currentMove = me;
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index e0ee7ed6698ab..cfb3e35bec54e 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -49,6 +49,7 @@ public abstract class KeyInputQueue {
static final String TAG = "KeyInputQueue";
static final boolean DEBUG_VIRTUAL_KEYS = false;
+ static final boolean DEBUG_POINTERS = false;
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
@@ -326,6 +327,10 @@ public abstract class KeyInputQueue {
config.navigation
= Configuration.NAVIGATION_TRACKBALL;
//Log.i("foo", "***** HAVE TRACKBALL!");
+ } else if ((d.classes&RawInputEvent.CLASS_DPAD) != 0) {
+ config.navigation
+ = Configuration.NAVIGATION_DPAD;
+ //Log.i("foo", "***** HAVE DPAD!");
}
}
}
@@ -364,9 +369,9 @@ public abstract class KeyInputQueue {
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
- try {
- RawInputEvent ev = new RawInputEvent();
- while (true) {
+ RawInputEvent ev = new RawInputEvent();
+ while (true) {
+ try {
InputDevice di;
// block, doesn't release the monitor
@@ -465,49 +470,81 @@ public abstract class KeyInputQueue {
? KeyEvent.FLAG_WOKE_HERE : 0));
} else if (ev.type == RawInputEvent.EV_KEY) {
if (ev.scancode == RawInputEvent.BTN_TOUCH &&
- (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+ (classes&(RawInputEvent.CLASS_TOUCHSCREEN
+ |RawInputEvent.CLASS_TOUCHSCREEN_MT))
+ == RawInputEvent.CLASS_TOUCHSCREEN) {
di.mAbs.changed = true;
di.mAbs.mDown[0] = ev.value != 0;
} else if (ev.scancode == RawInputEvent.BTN_2 &&
- (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+ (classes&(RawInputEvent.CLASS_TOUCHSCREEN
+ |RawInputEvent.CLASS_TOUCHSCREEN_MT))
+ == RawInputEvent.CLASS_TOUCHSCREEN) {
di.mAbs.changed = true;
di.mAbs.mDown[1] = ev.value != 0;
} else if (ev.scancode == RawInputEvent.BTN_MOUSE &&
(classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
di.mRel.changed = true;
- di.mRel.mDown[0] = ev.value != 0;
+ di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
send = true;
}
+ } else if (ev.type == RawInputEvent.EV_ABS &&
+ (classes&RawInputEvent.CLASS_TOUCHSCREEN_MT) != 0) {
+ if (ev.scancode == RawInputEvent.ABS_MT_TOUCH_MAJOR) {
+ di.mAbs.changed = true;
+ di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
+ + MotionEvent.SAMPLE_PRESSURE] = ev.value;
+ } else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_X) {
+ di.mAbs.changed = true;
+ di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
+ + MotionEvent.SAMPLE_X] = ev.value;
+ if (DEBUG_POINTERS) Log.v(TAG, "MT @"
+ + di.mAbs.mAddingPointerOffset
+ + " X:" + ev.value);
+ } else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_Y) {
+ di.mAbs.changed = true;
+ di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
+ + MotionEvent.SAMPLE_Y] = ev.value;
+ if (DEBUG_POINTERS) Log.v(TAG, "MT @"
+ + di.mAbs.mAddingPointerOffset
+ + " Y:" + ev.value);
+ } else if (ev.scancode == RawInputEvent.ABS_MT_WIDTH_MAJOR) {
+ di.mAbs.changed = true;
+ di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
+ + MotionEvent.SAMPLE_SIZE] = ev.value;
+ }
+
} else if (ev.type == RawInputEvent.EV_ABS &&
(classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
// Finger 1
if (ev.scancode == RawInputEvent.ABS_X) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.SAMPLE_X] = ev.value;
+ di.mAbs.mNextData[MotionEvent.SAMPLE_X] = ev.value;
} else if (ev.scancode == RawInputEvent.ABS_Y) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.SAMPLE_Y] = ev.value;
+ di.mAbs.mNextData[MotionEvent.SAMPLE_Y] = ev.value;
} else if (ev.scancode == RawInputEvent.ABS_PRESSURE) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
- di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+ di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
+ di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
+ MotionEvent.SAMPLE_PRESSURE] = ev.value;
} else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.SAMPLE_SIZE] = ev.value;
- di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+ di.mAbs.mNextData[MotionEvent.SAMPLE_SIZE] = ev.value;
+ di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
+ MotionEvent.SAMPLE_SIZE] = ev.value;
// Finger 2
} else if (ev.scancode == RawInputEvent.ABS_HAT0X) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
- + MotionEvent.SAMPLE_X] = ev.value;
+ di.mAbs.mNextData[(di.mAbs.mDown[0] ?
+ MotionEvent.NUM_SAMPLE_DATA : 0)
+ + MotionEvent.SAMPLE_X] = ev.value;
} else if (ev.scancode == RawInputEvent.ABS_HAT0Y) {
di.mAbs.changed = true;
- di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
- + MotionEvent.SAMPLE_Y] = ev.value;
+ di.mAbs.mNextData[(di.mAbs.mDown[0] ?
+ MotionEvent.NUM_SAMPLE_DATA : 0)
+ + MotionEvent.SAMPLE_Y] = ev.value;
}
} else if (ev.type == RawInputEvent.EV_REL &&
@@ -515,14 +552,40 @@ public abstract class KeyInputQueue {
// Add this relative movement into our totals.
if (ev.scancode == RawInputEvent.REL_X) {
di.mRel.changed = true;
- di.mRel.mCurData[MotionEvent.SAMPLE_X] += ev.value;
+ di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
} else if (ev.scancode == RawInputEvent.REL_Y) {
di.mRel.changed = true;
- di.mRel.mCurData[MotionEvent.SAMPLE_Y] += ev.value;
+ di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
}
}
- if (send || ev.type == RawInputEvent.EV_SYN) {
+ if (ev.type == RawInputEvent.EV_SYN
+ && ev.scancode == RawInputEvent.SYN_MT_REPORT
+ && di.mAbs != null) {
+ di.mAbs.changed = true;
+ if (di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] > 0) {
+ // If the value is <= 0, the pointer is not
+ // down, so keep it in the count.
+
+ if (di.mAbs.mNextData[di.mAbs.mAddingPointerOffset
+ + MotionEvent.SAMPLE_PRESSURE] != 0) {
+ final int num = di.mAbs.mNextNumPointers+1;
+ di.mAbs.mNextNumPointers = num;
+ if (DEBUG_POINTERS) Log.v(TAG,
+ "MT_REPORT: now have " + num + " pointers");
+ final int newOffset = (num <= InputDevice.MAX_POINTERS)
+ ? (num * MotionEvent.NUM_SAMPLE_DATA)
+ : (InputDevice.MAX_POINTERS *
+ MotionEvent.NUM_SAMPLE_DATA);
+ di.mAbs.mAddingPointerOffset = newOffset;
+ di.mAbs.mNextData[newOffset
+ + MotionEvent.SAMPLE_PRESSURE] = 0;
+ } else {
+ if (DEBUG_POINTERS) Log.v(TAG, "MT_REPORT: no pointer");
+ }
+ }
+ } else if (send || (ev.type == RawInputEvent.EV_SYN
+ && ev.scancode == RawInputEvent.SYN_REPORT)) {
if (mDisplay != null) {
if (!mHaveGlobalMetaState) {
computeGlobalMetaStateLocked();
@@ -534,72 +597,21 @@ public abstract class KeyInputQueue {
if (ms.changed) {
ms.changed = false;
- boolean doMotion = true;
-
- // Look for virtual buttons.
- VirtualKey vk = mPressedVirtualKey;
- if (vk != null) {
- doMotion = false;
- if (!ms.mDown[0]) {
- mPressedVirtualKey = null;
- ms.mLastDown[0] = ms.mDown[0];
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
- "Generate key up for: " + vk.scancode);
- KeyEvent event = newKeyEvent(di,
- di.mKeyDownTime, curTime, false,
- vk.lastKeycode,
- 0, vk.scancode,
- KeyEvent.FLAG_VIRTUAL_HARD_KEY);
- mHapticFeedbackCallback.virtualKeyFeedback(event);
- addLocked(di, curTimeNano, ev.flags,
- RawInputEvent.CLASS_KEYBOARD,
- event);
- } else if (isInsideDisplay(di)) {
- // Whoops the pointer has moved into
- // the display area! Cancel the
- // virtual key and start a pointer
- // motion.
- mPressedVirtualKey = null;
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
- "Cancel key up for: " + vk.scancode);
- KeyEvent event = newKeyEvent(di,
- di.mKeyDownTime, curTime, false,
- vk.lastKeycode,
- 0, vk.scancode,
- KeyEvent.FLAG_CANCELED |
- KeyEvent.FLAG_VIRTUAL_HARD_KEY);
- mHapticFeedbackCallback.virtualKeyFeedback(event);
- addLocked(di, curTimeNano, ev.flags,
- RawInputEvent.CLASS_KEYBOARD,
- event);
- doMotion = true;
- for (int i=InputDevice.MAX_POINTERS-1; i>=0; i--) {
- ms.mLastDown[i] = false;
- }
- }
+ if ((classes&(RawInputEvent.CLASS_TOUCHSCREEN
+ |RawInputEvent.CLASS_TOUCHSCREEN_MT))
+ == RawInputEvent.CLASS_TOUCHSCREEN) {
+ ms.mNextNumPointers = 0;
+ if (ms.mDown[0]) ms.mNextNumPointers++;
+ if (ms.mDown[1]) ms.mNextNumPointers++;
}
- if (doMotion && ms.mDown[0] && !ms.mLastDown[0]) {
- vk = findSoftButton(di);
- if (vk != null) {
- doMotion = false;
- mPressedVirtualKey = vk;
- vk.lastKeycode = scancodeToKeycode(
- di.id, vk.scancode);
- ms.mLastDown[0] = ms.mDown[0];
- di.mKeyDownTime = curTime;
- if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
- "Generate key down for: " + vk.scancode
- + " (keycode=" + vk.lastKeycode + ")");
- KeyEvent event = newKeyEvent(di,
- di.mKeyDownTime, curTime, true,
- vk.lastKeycode, 0,
- vk.scancode,
- KeyEvent.FLAG_VIRTUAL_HARD_KEY);
- mHapticFeedbackCallback.virtualKeyFeedback(event);
- addLocked(di, curTimeNano, ev.flags,
- RawInputEvent.CLASS_KEYBOARD,
- event);
- }
+
+ boolean doMotion = !monitorVirtualKey(di,
+ ev, curTime, curTimeNano);
+
+ if (doMotion && ms.mNextNumPointers > 0
+ && ms.mLastNumPointers == 0) {
+ doMotion = !generateVirtualKeyDown(di,
+ ev, curTime, curTimeNano);
}
if (doMotion) {
@@ -607,22 +619,26 @@ public abstract class KeyInputQueue {
// multiple events here, for example
// if two fingers change up/down state
// at the same time.
- me = ms.generateAbsMotion(di, curTime,
- curTimeNano, mDisplay,
- mOrientation, mGlobalMetaState);
- if (false) Log.v(TAG, "Absolute: x="
- + di.mAbs.mCurData[MotionEvent.SAMPLE_X]
- + " y="
- + di.mAbs.mCurData[MotionEvent.SAMPLE_Y]
- + " ev=" + me);
- if (me != null) {
- if (WindowManagerPolicy.WATCH_POINTER) {
- Log.i(TAG, "Enqueueing: " + me);
+ do {
+ me = ms.generateAbsMotion(di, curTime,
+ curTimeNano, mDisplay,
+ mOrientation, mGlobalMetaState);
+ if (false) Log.v(TAG, "Absolute: x="
+ + di.mAbs.mNextData[MotionEvent.SAMPLE_X]
+ + " y="
+ + di.mAbs.mNextData[MotionEvent.SAMPLE_Y]
+ + " ev=" + me);
+ if (me != null) {
+ if (WindowManagerPolicy.WATCH_POINTER) {
+ Log.i(TAG, "Enqueueing: " + me);
+ }
+ addLocked(di, curTimeNano, ev.flags,
+ RawInputEvent.CLASS_TOUCHSCREEN, me);
}
- addLocked(di, curTimeNano, ev.flags,
- RawInputEvent.CLASS_TOUCHSCREEN, me);
- }
+ } while (ms.hasMore());
}
+
+ ms.finish();
}
ms = di.mRel;
@@ -633,22 +649,24 @@ public abstract class KeyInputQueue {
curTimeNano,
mOrientation, mGlobalMetaState);
if (false) Log.v(TAG, "Relative: x="
- + di.mRel.mCurData[MotionEvent.SAMPLE_X]
+ + di.mRel.mNextData[MotionEvent.SAMPLE_X]
+ " y="
- + di.mRel.mCurData[MotionEvent.SAMPLE_Y]
+ + di.mRel.mNextData[MotionEvent.SAMPLE_Y]
+ " ev=" + me);
if (me != null) {
addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_TRACKBALL, me);
}
+
+ ms.finish();
}
}
}
}
- }
- } catch (RuntimeException exc) {
- Log.e(TAG, "InputReaderThread uncaught exception", exc);
+ } catch (RuntimeException exc) {
+ Log.e(TAG, "InputReaderThread uncaught exception", exc);
+ }
}
}
};
@@ -661,13 +679,13 @@ public abstract class KeyInputQueue {
return true;
}
- if (absm.mCurData[MotionEvent.SAMPLE_X] >= absx.minValue
- && absm.mCurData[MotionEvent.SAMPLE_X] <= absx.maxValue
- && absm.mCurData[MotionEvent.SAMPLE_Y] >= absy.minValue
- && absm.mCurData[MotionEvent.SAMPLE_Y] <= absy.maxValue) {
+ if (absm.mNextData[MotionEvent.SAMPLE_X] >= absx.minValue
+ && absm.mNextData[MotionEvent.SAMPLE_X] <= absx.maxValue
+ && absm.mNextData[MotionEvent.SAMPLE_Y] >= absy.minValue
+ && absm.mNextData[MotionEvent.SAMPLE_Y] <= absy.maxValue) {
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input ("
- + absm.mCurData[MotionEvent.SAMPLE_X]
- + "," + absm.mCurData[MotionEvent.SAMPLE_Y]
+ + absm.mNextData[MotionEvent.SAMPLE_X]
+ + "," + absm.mNextData[MotionEvent.SAMPLE_Y]
+ ") inside of display");
return true;
}
@@ -675,28 +693,24 @@ public abstract class KeyInputQueue {
return false;
}
- private VirtualKey findSoftButton(InputDevice dev) {
+ private VirtualKey findVirtualKey(InputDevice dev) {
final int N = mVirtualKeys.size();
if (N <= 0) {
return null;
}
- if (isInsideDisplay(dev)) {
- return null;
- }
-
final InputDevice.MotionState absm = dev.mAbs;
for (int i=0; i