am 42bb545a: am 5c225b16: Even more native input dispatch work in progress.
Merge commit '42bb545a54d89f0ddbb230d7a01ea4210c0f6c00'
* commit '42bb545a54d89f0ddbb230d7a01ea4210c0f6c00':
Even more native input dispatch work in progress.
diff --git a/api/current.xml b/api/current.xml
index e4ce4a4..da21f54 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -180121,7 +180121,7 @@
synchronized="false"
static="true"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="downTime" type="long">
@@ -180256,7 +180256,7 @@
native="false"
synchronized="false"
static="false"
- final="false"
+ final="true"
deprecated="not deprecated"
visibility="public"
>
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 1f06191..ae8c21d 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -27,6 +27,7 @@
* it is being used for.
*/
public final class MotionEvent implements Parcelable {
+ private static final long MS_PER_NS = 1000000;
static final boolean DEBUG_POINTERS = false;
/**
@@ -218,31 +219,32 @@
static private int gRecyclerUsed = 0;
static private MotionEvent gRecyclerTop = null;
- private long mDownTime;
- private long mEventTimeNano;
+ private long mDownTimeNano;
private int mAction;
- private float mRawX;
- private float mRawY;
+ private float mXOffset;
+ private float mYOffset;
private float mXPrecision;
private float mYPrecision;
private int mDeviceId;
private int mEdgeFlags;
private int mMetaState;
- // Here is the actual event data. Note that the order of the array
- // is a little odd: the first entry is the most recent, and the ones
- // following it are the historical data from oldest to newest. This
- // allows us to easily retrieve the most recent data, without having
- // to copy the arrays every time a new sample is added.
-
private int mNumPointers;
private int mNumSamples;
+
+ private int mLastDataSampleIndex;
+ private int mLastEventTimeNanoSampleIndex;
+
// 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.
+ // Samples are ordered from oldest to newest.
private float[] mDataSamples;
- // Array of mNumSamples size of time stamps.
- private long[] mTimeSamples;
+
+ // Array of mNumSamples size of event time stamps in nanoseconds.
+ // Samples are ordered from oldest to newest.
+ private long[] mEventTimeNanoSamples;
private MotionEvent mNext;
private RuntimeException mRecycledLocation;
@@ -251,26 +253,9 @@
private MotionEvent(int pointerCount, int sampleCount) {
mPointerIdentifiers = new int[pointerCount];
mDataSamples = new float[pointerCount * sampleCount * NUM_SAMPLE_DATA];
- mTimeSamples = new long[sampleCount];
+ mEventTimeNanoSamples = new long[sampleCount];
}
- static private MotionEvent obtain() {
- final MotionEvent ev;
- synchronized (gRecyclerLock) {
- if (gRecyclerTop == null) {
- return new MotionEvent(BASE_AVAIL_POINTERS, BASE_AVAIL_SAMPLES);
- }
- ev = gRecyclerTop;
- gRecyclerTop = ev.mNext;
- gRecyclerUsed--;
- }
- ev.mRecycledLocation = null;
- ev.mRecycled = false;
- ev.mNext = null;
- return ev;
- }
-
- @SuppressWarnings("unused") // used by native code
static private MotionEvent obtain(int pointerCount, int sampleCount) {
final MotionEvent ev;
synchronized (gRecyclerLock) {
@@ -285,7 +270,7 @@
}
ev = gRecyclerTop;
gRecyclerTop = ev.mNext;
- gRecyclerUsed--;
+ gRecyclerUsed -= 1;
}
ev.mRecycledLocation = null;
ev.mRecycled = false;
@@ -295,20 +280,18 @@
ev.mPointerIdentifiers = new int[pointerCount];
}
- final int timeSamplesLength = ev.mTimeSamples.length;
- if (timeSamplesLength < sampleCount) {
- ev.mTimeSamples = new long[sampleCount];
+ if (ev.mEventTimeNanoSamples.length < sampleCount) {
+ ev.mEventTimeNanoSamples = new long[sampleCount];
}
- final int dataSamplesLength = ev.mDataSamples.length;
final int neededDataSamplesLength = pointerCount * sampleCount * NUM_SAMPLE_DATA;
- if (dataSamplesLength < neededDataSamplesLength) {
+ if (ev.mDataSamples.length < neededDataSamplesLength) {
ev.mDataSamples = new float[neededDataSamplesLength];
}
return ev;
}
-
+
/**
* Create a new MotionEvent, filling in all of the basic values that
* define the motion.
@@ -342,45 +325,39 @@
static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
int action, int pointers, int[] inPointerIds, float[] inData, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
- MotionEvent ev = obtain();
+ MotionEvent ev = obtain(pointers, 1);
ev.mDeviceId = deviceId;
ev.mEdgeFlags = edgeFlags;
- ev.mDownTime = downTime;
- ev.mEventTimeNano = eventTimeNano;
+ ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action;
ev.mMetaState = metaState;
- ev.mRawX = inData[SAMPLE_X];
- ev.mRawY = inData[SAMPLE_Y];
+ ev.mXOffset = 0;
+ ev.mYOffset = 0;
ev.mXPrecision = xPrecision;
ev.mYPrecision = yPrecision;
+
ev.mNumPointers = pointers;
ev.mNumSamples = 1;
- int[] pointerIdentifiers = ev.mPointerIdentifiers;
- if (pointerIdentifiers.length < pointers) {
- ev.mPointerIdentifiers = pointerIdentifiers = new int[pointers];
- }
- System.arraycopy(inPointerIds, 0, pointerIdentifiers, 0, pointers);
+ ev.mLastDataSampleIndex = 0;
+ ev.mLastEventTimeNanoSampleIndex = 0;
- final int ND = pointers * NUM_SAMPLE_DATA;
- float[] dataSamples = ev.mDataSamples;
- if (dataSamples.length < ND) {
- ev.mDataSamples = dataSamples = new float[ND];
- }
- System.arraycopy(inData, 0, dataSamples, 0, ND);
+ System.arraycopy(inPointerIds, 0, ev.mPointerIdentifiers, 0, pointers);
- ev.mTimeSamples[0] = eventTime;
+ ev.mEventTimeNanoSamples[0] = eventTimeNano;
+
+ System.arraycopy(inData, 0, ev.mDataSamples, 0, pointers * NUM_SAMPLE_DATA);
if (DEBUG_POINTERS) {
StringBuilder sb = new StringBuilder(128);
sb.append("New:");
- for (int i=0; i<pointers; i++) {
+ for (int i = 0; i < pointers; i++) {
sb.append(" #");
- sb.append(ev.mPointerIdentifiers[i]);
+ sb.append(ev.getPointerId(i));
sb.append("(");
- sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
+ sb.append(ev.getX(i));
sb.append(",");
- sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
+ sb.append(ev.getY(i));
sb.append(")");
}
Log.v("MotionEvent", sb.toString());
@@ -423,27 +400,32 @@
static public MotionEvent obtain(long downTime, long eventTime, int action,
float x, float y, float pressure, float size, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
- MotionEvent ev = obtain();
+ MotionEvent ev = obtain(1, 1);
ev.mDeviceId = deviceId;
ev.mEdgeFlags = edgeFlags;
- ev.mDownTime = downTime;
- ev.mEventTimeNano = eventTime * 1000000;
+ ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action;
ev.mMetaState = metaState;
+ ev.mXOffset = 0;
+ ev.mYOffset = 0;
ev.mXPrecision = xPrecision;
ev.mYPrecision = yPrecision;
-
+
ev.mNumPointers = 1;
ev.mNumSamples = 1;
- int[] pointerIds = ev.mPointerIdentifiers;
- pointerIds[0] = 0;
- float[] data = ev.mDataSamples;
- data[SAMPLE_X] = ev.mRawX = x;
- data[SAMPLE_Y] = ev.mRawY = y;
- data[SAMPLE_PRESSURE] = pressure;
- data[SAMPLE_SIZE] = size;
- ev.mTimeSamples[0] = eventTime;
-
+
+ ev.mLastDataSampleIndex = 0;
+ ev.mLastEventTimeNanoSampleIndex = 0;
+
+ ev.mPointerIdentifiers[0] = 0;
+
+ ev.mEventTimeNanoSamples[0] = eventTime * MS_PER_NS;
+
+ float[] dataSamples = ev.mDataSamples;
+ dataSamples[SAMPLE_X] = x;
+ dataSamples[SAMPLE_Y] = y;
+ dataSamples[SAMPLE_PRESSURE] = pressure;
+ dataSamples[SAMPLE_SIZE] = size;
return ev;
}
@@ -478,33 +460,16 @@
* numbers are arbitrary and you shouldn't depend on the values.
* @param edgeFlags A bitfield indicating which edges, if any, where touched by this
* MotionEvent.
+ *
+ * @deprecated Use {@link #obtain(long, long, int, float, float, float, float, int, float, float, int, int)}
+ * instead.
*/
+ @Deprecated
static public MotionEvent obtain(long downTime, long eventTime, int action,
int pointers, float x, float y, float pressure, float size, int metaState,
float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
- MotionEvent ev = obtain();
- ev.mDeviceId = deviceId;
- ev.mEdgeFlags = edgeFlags;
- ev.mDownTime = downTime;
- ev.mEventTimeNano = eventTime * 1000000;
- ev.mAction = action;
- ev.mNumPointers = pointers;
- ev.mMetaState = metaState;
- ev.mXPrecision = xPrecision;
- ev.mYPrecision = yPrecision;
-
- ev.mNumPointers = 1;
- ev.mNumSamples = 1;
- int[] pointerIds = ev.mPointerIdentifiers;
- pointerIds[0] = 0;
- float[] data = ev.mDataSamples;
- data[SAMPLE_X] = ev.mRawX = x;
- data[SAMPLE_Y] = ev.mRawY = y;
- data[SAMPLE_PRESSURE] = pressure;
- data[SAMPLE_SIZE] = size;
- ev.mTimeSamples[0] = eventTime;
-
- return ev;
+ return obtain(downTime, eventTime, action, x, y, pressure, size,
+ metaState, xPrecision, yPrecision, deviceId, edgeFlags);
}
/**
@@ -526,89 +491,36 @@
*/
static public MotionEvent obtain(long downTime, long eventTime, int action,
float x, float y, int metaState) {
- MotionEvent ev = obtain();
- ev.mDeviceId = 0;
- ev.mEdgeFlags = 0;
- ev.mDownTime = downTime;
- ev.mEventTimeNano = eventTime * 1000000;
- ev.mAction = action;
- ev.mNumPointers = 1;
- ev.mMetaState = metaState;
- ev.mXPrecision = 1.0f;
- ev.mYPrecision = 1.0f;
-
- ev.mNumPointers = 1;
- ev.mNumSamples = 1;
- int[] pointerIds = ev.mPointerIdentifiers;
- pointerIds[0] = 0;
- float[] data = ev.mDataSamples;
- data[SAMPLE_X] = ev.mRawX = x;
- data[SAMPLE_Y] = ev.mRawY = y;
- data[SAMPLE_PRESSURE] = 1.0f;
- data[SAMPLE_SIZE] = 1.0f;
- ev.mTimeSamples[0] = eventTime;
-
- return ev;
- }
-
- /**
- * Scales down the coordination of this event by the given scale.
- *
- * @hide
- */
- public void scale(float scale) {
- mRawX *= scale;
- mRawY *= scale;
- mXPrecision *= scale;
- mYPrecision *= scale;
- float[] history = mDataSamples;
- final int length = mNumPointers * mNumSamples * NUM_SAMPLE_DATA;
- for (int i = 0; i < length; i += NUM_SAMPLE_DATA) {
- history[i + SAMPLE_X] *= scale;
- history[i + SAMPLE_Y] *= scale;
- // no need to scale pressure
- history[i + SAMPLE_SIZE] *= scale; // TODO: square this?
- }
+ return obtain(downTime, eventTime, action, x, y, 1.0f, 1.0f,
+ metaState, 1.0f, 1.0f, 0, 0);
}
/**
* Create a new MotionEvent, copying from an existing one.
*/
static public MotionEvent obtain(MotionEvent o) {
- MotionEvent ev = obtain();
+ MotionEvent ev = obtain(o.mNumPointers, o.mNumSamples);
ev.mDeviceId = o.mDeviceId;
ev.mEdgeFlags = o.mEdgeFlags;
- ev.mDownTime = o.mDownTime;
- ev.mEventTimeNano = o.mEventTimeNano;
+ ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction;
- ev.mNumPointers = o.mNumPointers;
- ev.mRawX = o.mRawX;
- ev.mRawY = o.mRawY;
ev.mMetaState = o.mMetaState;
+ ev.mXOffset = o.mXOffset;
+ ev.mYOffset = o.mYOffset;
ev.mXPrecision = o.mXPrecision;
ev.mYPrecision = o.mYPrecision;
+ int numPointers = ev.mNumPointers = o.mNumPointers;
+ int numSamples = ev.mNumSamples = o.mNumSamples;
- 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();
- }
+ ev.mLastDataSampleIndex = o.mLastDataSampleIndex;
+ ev.mLastEventTimeNanoSampleIndex = o.mLastEventTimeNanoSampleIndex;
- final int NP = (ev.mNumPointers=o.mNumPointers);
- if (ev.mPointerIdentifiers.length >= NP) {
- System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
- } else {
- ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
- }
+ System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, numPointers);
- final int ND = NP * NS * NUM_SAMPLE_DATA;
- if (ev.mDataSamples.length >= ND) {
- System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
- } else {
- ev.mDataSamples = (float[])o.mDataSamples.clone();
- }
+ System.arraycopy(o.mEventTimeNanoSamples, 0, ev.mEventTimeNanoSamples, 0, numSamples);
+ System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0,
+ numPointers * numSamples * NUM_SAMPLE_DATA);
return ev;
}
@@ -617,36 +529,29 @@
* any historical point information.
*/
static public MotionEvent obtainNoHistory(MotionEvent o) {
- MotionEvent ev = obtain();
+ MotionEvent ev = obtain(o.mNumPointers, 1);
ev.mDeviceId = o.mDeviceId;
ev.mEdgeFlags = o.mEdgeFlags;
- ev.mDownTime = o.mDownTime;
- ev.mEventTimeNano = o.mEventTimeNano;
+ ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction;
- ev.mNumPointers = o.mNumPointers;
- ev.mRawX = o.mRawX;
- ev.mRawY = o.mRawY;
ev.mMetaState = o.mMetaState;
+ ev.mXOffset = o.mXOffset;
+ ev.mYOffset = o.mYOffset;
ev.mXPrecision = o.mXPrecision;
ev.mYPrecision = o.mYPrecision;
+ int numPointers = ev.mNumPointers = o.mNumPointers;
ev.mNumSamples = 1;
- ev.mTimeSamples[0] = o.mTimeSamples[0];
- final int NP = (ev.mNumPointers=o.mNumPointers);
- if (ev.mPointerIdentifiers.length >= NP) {
- System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
- } else {
- ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
- }
+ ev.mLastDataSampleIndex = 0;
+ ev.mLastEventTimeNanoSampleIndex = 0;
- final int ND = NP * NUM_SAMPLE_DATA;
- if (ev.mDataSamples.length >= ND) {
- System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
- } else {
- ev.mDataSamples = (float[])o.mDataSamples.clone();
- }
+ System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, numPointers);
+ ev.mEventTimeNanoSamples[0] = o.mEventTimeNanoSamples[o.mLastEventTimeNanoSampleIndex];
+
+ System.arraycopy(o.mDataSamples, o.mLastDataSampleIndex, ev.mDataSamples, 0,
+ numPointers * NUM_SAMPLE_DATA);
return ev;
}
@@ -654,7 +559,7 @@
* Recycle the MotionEvent, to be re-used by a later caller. After calling
* this function you must not ever touch the event again.
*/
- public void recycle() {
+ public final void recycle() {
// Ensure recycle is only called once!
if (TRACK_RECYCLED_LOCATION) {
if (mRecycledLocation != null) {
@@ -678,6 +583,27 @@
}
}
}
+
+ /**
+ * Scales down the coordination of this event by the given scale.
+ *
+ * @hide
+ */
+ public final void scale(float scale) {
+ mXOffset *= scale;
+ mYOffset *= scale;
+ mXPrecision *= scale;
+ mYPrecision *= scale;
+
+ float[] history = mDataSamples;
+ final int length = mNumPointers * mNumSamples * NUM_SAMPLE_DATA;
+ for (int i = 0; i < length; i += NUM_SAMPLE_DATA) {
+ history[i + SAMPLE_X] *= scale;
+ history[i + SAMPLE_Y] *= scale;
+ // no need to scale pressure
+ history[i + SAMPLE_SIZE] *= scale; // TODO: square this?
+ }
+ }
/**
* Return the kind of action being performed -- one of either
@@ -719,14 +645,14 @@
* a stream of position events.
*/
public final long getDownTime() {
- return mDownTime;
+ return mDownTimeNano / MS_PER_NS;
}
/**
* Returns the time (in ms) when this specific event was generated.
*/
public final long getEventTime() {
- return mTimeSamples[0];
+ return mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] / MS_PER_NS;
}
/**
@@ -736,7 +662,7 @@
* @hide
*/
public final long getEventTimeNano() {
- return mEventTimeNano;
+ return mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex];
}
/**
@@ -744,7 +670,7 @@
* arbitrary pointer identifier).
*/
public final float getX() {
- return mDataSamples[SAMPLE_X];
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_X] + mXOffset;
}
/**
@@ -752,7 +678,7 @@
* arbitrary pointer identifier).
*/
public final float getY() {
- return mDataSamples[SAMPLE_Y];
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_Y] + mYOffset;
}
/**
@@ -760,7 +686,7 @@
* arbitrary pointer identifier).
*/
public final float getPressure() {
- return mDataSamples[SAMPLE_PRESSURE];
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_PRESSURE];
}
/**
@@ -768,7 +694,7 @@
* arbitrary pointer identifier).
*/
public final float getSize() {
- return mDataSamples[SAMPLE_SIZE];
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_SIZE];
}
/**
@@ -820,7 +746,8 @@
* (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
public final float getX(int pointerIndex) {
- return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_X];
+ return mDataSamples[mLastDataSampleIndex
+ + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset;
}
/**
@@ -833,7 +760,8 @@
* (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
public final float getY(int pointerIndex) {
- return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_Y];
+ return mDataSamples[mLastDataSampleIndex
+ + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset;
}
/**
@@ -848,7 +776,8 @@
* (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
public final float getPressure(int pointerIndex) {
- return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
+ return mDataSamples[mLastDataSampleIndex
+ + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_PRESSURE];
}
/**
@@ -864,7 +793,8 @@
* (the first pointer that is down) to {@link #getPointerCount()}-1.
*/
public final float getSize(int pointerIndex) {
- return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
+ return mDataSamples[mLastDataSampleIndex
+ + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_SIZE];
}
/**
@@ -888,7 +818,7 @@
* and views.
*/
public final float getRawX() {
- return mRawX;
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_X];
}
/**
@@ -898,7 +828,7 @@
* and views.
*/
public final float getRawY() {
- return mRawY;
+ return mDataSamples[mLastDataSampleIndex + SAMPLE_Y];
}
/**
@@ -930,7 +860,7 @@
* @return Returns the number of historical points in the event.
*/
public final int getHistorySize() {
- return mNumSamples - 1;
+ return mLastEventTimeNanoSampleIndex;
}
/**
@@ -944,7 +874,7 @@
* @see #getEventTime
*/
public final long getHistoricalEventTime(int pos) {
- return mTimeSamples[pos + 1];
+ return mEventTimeNanoSamples[pos] / MS_PER_NS;
}
/**
@@ -952,7 +882,7 @@
* arbitrary pointer identifier).
*/
public final float getHistoricalX(int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_X];
+ return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset;
}
/**
@@ -960,7 +890,7 @@
* arbitrary pointer identifier).
*/
public final float getHistoricalY(int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_Y];
+ return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset;
}
/**
@@ -968,7 +898,7 @@
* arbitrary pointer identifier).
*/
public final float getHistoricalPressure(int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_PRESSURE];
+ return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_PRESSURE];
}
/**
@@ -976,7 +906,7 @@
* arbitrary pointer identifier).
*/
public final float getHistoricalSize(int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_SIZE];
+ return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_SIZE];
}
/**
@@ -993,8 +923,8 @@
* @see #getX
*/
public final float getHistoricalX(int pointerIndex, int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_X];
+ return mDataSamples[(pos * mNumPointers + pointerIndex)
+ * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset;
}
/**
@@ -1011,8 +941,8 @@
* @see #getY
*/
public final float getHistoricalY(int pointerIndex, int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_Y];
+ return mDataSamples[(pos * mNumPointers + pointerIndex)
+ * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset;
}
/**
@@ -1029,8 +959,8 @@
* @see #getPressure
*/
public final float getHistoricalPressure(int pointerIndex, int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
+ return mDataSamples[(pos * mNumPointers + pointerIndex)
+ * NUM_SAMPLE_DATA + SAMPLE_PRESSURE];
}
/**
@@ -1047,8 +977,8 @@
* @see #getSize
*/
public final float getHistoricalSize(int pointerIndex, int pos) {
- return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
- + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
+ return mDataSamples[(pos * mNumPointers + pointerIndex)
+ * NUM_SAMPLE_DATA + SAMPLE_SIZE];
}
/**
@@ -1098,12 +1028,8 @@
* @param deltaY Amount to add to the current Y coordinate of the event.
*/
public final void offsetLocation(float deltaX, float deltaY) {
- final int N = mNumPointers*mNumSamples*4;
- final float[] pos = mDataSamples;
- for (int i=0; i<N; i+=NUM_SAMPLE_DATA) {
- pos[i+SAMPLE_X] += deltaX;
- pos[i+SAMPLE_Y] += deltaY;
- }
+ mXOffset += deltaX;
+ mYOffset += deltaY;
}
/**
@@ -1114,11 +1040,28 @@
* @param y New absolute Y location.
*/
public final void setLocation(float x, float y) {
- float deltaX = x-mDataSamples[SAMPLE_X];
- float deltaY = y-mDataSamples[SAMPLE_Y];
- if (deltaX != 0 || deltaY != 0) {
- offsetLocation(deltaX, deltaY);
+ mXOffset = x - mDataSamples[mLastDataSampleIndex + SAMPLE_X];
+ mYOffset = y - mDataSamples[mLastDataSampleIndex + SAMPLE_Y];
+ }
+
+ private final void incrementNumSamplesAndReserveStorage(int dataSampleStride) {
+ if (mNumSamples == mEventTimeNanoSamples.length) {
+ long[] newEventTimeNanoSamples = new long[mNumSamples + BASE_AVAIL_SAMPLES];
+ System.arraycopy(mEventTimeNanoSamples, 0, newEventTimeNanoSamples, 0, mNumSamples);
+ mEventTimeNanoSamples = newEventTimeNanoSamples;
}
+
+ int nextDataSampleIndex = mLastDataSampleIndex + dataSampleStride;
+ if (nextDataSampleIndex + dataSampleStride > mDataSamples.length) {
+ float[] newDataSamples = new float[nextDataSampleIndex
+ + BASE_AVAIL_SAMPLES * dataSampleStride];
+ System.arraycopy(mDataSamples, 0, newDataSamples, 0, nextDataSampleIndex);
+ mDataSamples = newDataSamples;
+ }
+
+ mLastEventTimeNanoSampleIndex = mNumSamples;
+ mLastDataSampleIndex = nextDataSampleIndex;
+ mNumSamples += 1;
}
/**
@@ -1136,42 +1079,16 @@
*/
public final void addBatch(long eventTime, float x, float y,
float pressure, float size, int metaState) {
- float[] data = mDataSamples;
- long[] times = mTimeSamples;
+ incrementNumSamplesAndReserveStorage(NUM_SAMPLE_DATA);
- final int NP = mNumPointers;
- final int NS = mNumSamples;
- final int NI = NP*NS;
- final int ND = 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;
- }
- if (times.length <= NS) {
- final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
- long[] newHistoryTimes = new long[NEW_NS];
- System.arraycopy(times, 0, newHistoryTimes, 0, NS);
- mTimeSamples = times = newHistoryTimes;
- }
+ mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS;
- times[NS] = times[0];
- times[0] = eventTime;
+ float[] dataSamples = mDataSamples;
+ dataSamples[mLastDataSampleIndex + SAMPLE_X] = x - mXOffset;
+ dataSamples[mLastDataSampleIndex + SAMPLE_Y] = y - mYOffset;
+ dataSamples[mLastDataSampleIndex + SAMPLE_PRESSURE] = pressure;
+ dataSamples[mLastDataSampleIndex + SAMPLE_SIZE] = size;
- final int pos = NS*NUM_SAMPLE_DATA;
- data[pos+SAMPLE_X] = data[SAMPLE_X];
- data[pos+SAMPLE_Y] = data[SAMPLE_Y];
- data[pos+SAMPLE_PRESSURE] = data[SAMPLE_PRESSURE];
- data[pos+SAMPLE_SIZE] = data[SAMPLE_SIZE];
- data[SAMPLE_X] = x;
- data[SAMPLE_Y] = y;
- data[SAMPLE_PRESSURE] = pressure;
- data[SAMPLE_SIZE] = size;
- mNumSamples = NS+1;
-
- mRawX = x;
- mRawY = y;
mMetaState |= metaState;
}
@@ -1187,48 +1104,36 @@
* @hide
*/
public final void addBatch(long eventTime, float[] inData, int metaState) {
- float[] data = mDataSamples;
- long[] times = mTimeSamples;
+ final int numPointers = mNumPointers;
+ final int dataSampleStride = numPointers * NUM_SAMPLE_DATA;
+ incrementNumSamplesAndReserveStorage(dataSampleStride);
- final int NP = mNumPointers;
- final int NS = mNumSamples;
- final int NI = NP*NS;
- final int ND = NI * NUM_SAMPLE_DATA;
- if (data.length < (ND+(NP*NUM_SAMPLE_DATA))) {
- 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;
- }
- if (times.length < (NS+1)) {
- final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
- long[] newHistoryTimes = new long[NEW_NS];
- System.arraycopy(times, 0, newHistoryTimes, 0, NS);
- mTimeSamples = times = newHistoryTimes;
- }
+ mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS;
- times[NS] = times[0];
- times[0] = eventTime;
-
- System.arraycopy(data, 0, data, ND, mNumPointers*NUM_SAMPLE_DATA);
- System.arraycopy(inData, 0, data, 0, mNumPointers*NUM_SAMPLE_DATA);
-
- mNumSamples = NS+1;
+ float[] dataSamples = mDataSamples;
+ System.arraycopy(inData, 0, dataSamples, mLastDataSampleIndex, dataSampleStride);
- mRawX = inData[SAMPLE_X];
- mRawY = inData[SAMPLE_Y];
+ if (mXOffset != 0 || mYOffset != 0) {
+ int index = mLastEventTimeNanoSampleIndex;
+ for (int i = 0; i < numPointers; i++) {
+ dataSamples[index + SAMPLE_X] -= mXOffset;
+ dataSamples[index + SAMPLE_Y] -= mYOffset;
+ index += NUM_SAMPLE_DATA;
+ }
+ }
+
mMetaState |= metaState;
if (DEBUG_POINTERS) {
StringBuilder sb = new StringBuilder(128);
sb.append("Add:");
- for (int i=0; i<mNumPointers; i++) {
+ for (int i = 0; i < mNumPointers; i++) {
sb.append(" #");
- sb.append(mPointerIdentifiers[i]);
+ sb.append(getPointerId(i));
sb.append("(");
- sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
+ sb.append(getX(i));
sb.append(",");
- sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
+ sb.append(getY(i));
sb.append(")");
}
Log.v("MotionEvent", sb.toString());
@@ -1245,8 +1150,41 @@
public static final Parcelable.Creator<MotionEvent> CREATOR
= new Parcelable.Creator<MotionEvent>() {
public MotionEvent createFromParcel(Parcel in) {
- MotionEvent ev = obtain();
- ev.readFromParcel(in);
+ final int NP = in.readInt();
+ final int NS = in.readInt();
+ final int NI = NP * NS * NUM_SAMPLE_DATA;
+
+ MotionEvent ev = obtain(NP, NS);
+ ev.mNumPointers = NP;
+ ev.mNumSamples = NS;
+
+ ev.mDownTimeNano = in.readLong();
+ ev.mAction = in.readInt();
+ ev.mXOffset = in.readFloat();
+ ev.mYOffset = in.readFloat();
+ ev.mXPrecision = in.readFloat();
+ ev.mYPrecision = in.readFloat();
+ ev.mDeviceId = in.readInt();
+ ev.mEdgeFlags = in.readInt();
+ ev.mMetaState = in.readInt();
+
+ final int[] pointerIdentifiers = ev.mPointerIdentifiers;
+ for (int i = 0; i < NP; i++) {
+ pointerIdentifiers[i] = in.readInt();
+ }
+
+ final long[] eventTimeNanoSamples = ev.mEventTimeNanoSamples;
+ for (int i = 0; i < NS; i++) {
+ eventTimeNanoSamples[i] = in.readLong();
+ }
+
+ final float[] dataSamples = ev.mDataSamples;
+ for (int i = 0; i < NI; i++) {
+ dataSamples[i] = in.readFloat();
+ }
+
+ ev.mLastEventTimeNanoSampleIndex = NS - 1;
+ ev.mLastDataSampleIndex = (NS - 1) * NP * NUM_SAMPLE_DATA;
return ev;
}
@@ -1260,79 +1198,36 @@
}
public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mDownTime);
- out.writeLong(mEventTimeNano);
- out.writeInt(mAction);
- out.writeInt(mMetaState);
- out.writeFloat(mRawX);
- out.writeFloat(mRawY);
final int NP = mNumPointers;
- out.writeInt(NP);
final int NS = mNumSamples;
+ final int NI = NP * NS * NUM_SAMPLE_DATA;
+
+ out.writeInt(NP);
out.writeInt(NS);
- final int NI = NP*NS;
- if (NI > 0) {
- int i;
- int[] state = mPointerIdentifiers;
- for (i=0; i<NP; i++) {
- out.writeInt(state[i]);
- }
- final int ND = NI*NUM_SAMPLE_DATA;
- float[] history = mDataSamples;
- for (i=0; i<ND; i++) {
- out.writeFloat(history[i]);
- }
- long[] times = mTimeSamples;
- for (i=0; i<NS; i++) {
- out.writeLong(times[i]);
- }
- }
+
+ out.writeLong(mDownTimeNano);
+ out.writeInt(mAction);
+ out.writeFloat(mXOffset);
+ out.writeFloat(mYOffset);
out.writeFloat(mXPrecision);
out.writeFloat(mYPrecision);
out.writeInt(mDeviceId);
out.writeInt(mEdgeFlags);
- }
-
- private void readFromParcel(Parcel in) {
- mDownTime = in.readLong();
- mEventTimeNano = in.readLong();
- mAction = in.readInt();
- mMetaState = in.readInt();
- mRawX = in.readFloat();
- mRawY = in.readFloat();
- final int NP = in.readInt();
- mNumPointers = NP;
- final int NS = in.readInt();
- mNumSamples = NS;
- final int NI = NP*NS;
- if (NI > 0) {
- int[] ids = mPointerIdentifiers;
- if (ids.length < NP) {
- mPointerIdentifiers = ids = new int[NP];
- }
- for (int i=0; i<NP; i++) {
- ids[i] = in.readInt();
- }
- float[] history = mDataSamples;
- final int ND = NI*NUM_SAMPLE_DATA;
- if (history.length < ND) {
- mDataSamples = history = new float[ND];
- }
- for (int i=0; i<ND; i++) {
- history[i] = in.readFloat();
- }
- long[] times = mTimeSamples;
- if (times == null || times.length < NS) {
- mTimeSamples = times = new long[NS];
- }
- for (int i=0; i<NS; i++) {
- times[i] = in.readLong();
- }
+ out.writeInt(mMetaState);
+
+ final int[] pointerIdentifiers = mPointerIdentifiers;
+ for (int i = 0; i < NP; i++) {
+ out.writeInt(pointerIdentifiers[i]);
}
- mXPrecision = in.readFloat();
- mYPrecision = in.readFloat();
- mDeviceId = in.readInt();
- mEdgeFlags = in.readInt();
- }
+
+ final long[] eventTimeNanoSamples = mEventTimeNanoSamples;
+ for (int i = 0; i < NS; i++) {
+ out.writeLong(eventTimeNanoSamples[i]);
+ }
+ final float[] dataSamples = mDataSamples;
+ for (int i = 0; i < NI; i++) {
+ out.writeFloat(dataSamples[i]);
+ }
+ }
}
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 47bb073..4a4393a 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -121,9 +121,9 @@
String8 name(nameChars);
env->ReleaseStringUTFChars(nameObj, nameChars);
- InputChannel* serverChannel;
- InputChannel* clientChannel;
- status_t result = InputChannel::openInputChannelPair(name, & serverChannel, & clientChannel);
+ sp<InputChannel> serverChannel;
+ sp<InputChannel> clientChannel;
+ status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
LOGE("Could not open input channel pair. status=%d", result);
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 629c8fe..78137e2 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -36,11 +36,10 @@
jmethodID obtain;
jmethodID recycle;
- jfieldID mDownTime;
- jfieldID mEventTimeNano;
+ jfieldID mDownTimeNano;
jfieldID mAction;
- jfieldID mRawX;
- jfieldID mRawY;
+ jfieldID mXOffset;
+ jfieldID mYOffset;
jfieldID mXPrecision;
jfieldID mYPrecision;
jfieldID mDeviceId;
@@ -50,7 +49,9 @@
jfieldID mNumSamples;
jfieldID mPointerIdentifiers;
jfieldID mDataSamples;
- jfieldID mTimeSamples;
+ jfieldID mEventTimeNanoSamples;
+ jfieldID mLastDataSampleIndex;
+ jfieldID mLastEventTimeNanoSampleIndex;
} gMotionEventClassInfo;
// ----------------------------------------------------------------------------
@@ -69,22 +70,14 @@
return NULL;
}
- // MotionEvent.mEventTimeNano is the time of the oldest sample because
- // MotionEvent.addBatch does not update it as successive samples are added.
- jlong eventTimeNano = numHistoricalSamples != 0
- ? event->getHistoricalEventTime(0)
- : event->getEventTime();
-
- env->SetLongField(eventObj, gMotionEventClassInfo.mDownTime,
- nanoseconds_to_milliseconds(event->getDownTime()));
- env->SetLongField(eventObj, gMotionEventClassInfo.mEventTimeNano,
- eventTimeNano);
+ env->SetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano,
+ event->getDownTime());
env->SetIntField(eventObj, gMotionEventClassInfo.mAction,
event->getAction());
- env->SetFloatField(eventObj, gMotionEventClassInfo.mRawX,
- event->getRawX());
- env->SetFloatField(eventObj, gMotionEventClassInfo.mRawY,
- event->getRawY());
+ env->SetFloatField(eventObj, gMotionEventClassInfo.mXOffset,
+ event->getXOffset());
+ env->SetFloatField(eventObj, gMotionEventClassInfo.mYOffset,
+ event->getYOffset());
env->SetFloatField(eventObj, gMotionEventClassInfo.mXPrecision,
event->getXPrecision());
env->SetFloatField(eventObj, gMotionEventClassInfo.mYPrecision,
@@ -99,65 +92,62 @@
numPointers);
env->SetIntField(eventObj, gMotionEventClassInfo.mNumSamples,
numSamples);
+ env->SetIntField(eventObj, gMotionEventClassInfo.mLastDataSampleIndex,
+ (numSamples - 1) * numPointers * NUM_SAMPLE_DATA);
+ env->SetIntField(eventObj, gMotionEventClassInfo.mLastEventTimeNanoSampleIndex,
+ numSamples - 1);
jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj,
gMotionEventClassInfo.mPointerIdentifiers));
jfloatArray dataSampleArray = jfloatArray(env->GetObjectField(eventObj,
gMotionEventClassInfo.mDataSamples));
- jlongArray timeSampleArray = jlongArray(env->GetObjectField(eventObj,
- gMotionEventClassInfo.mTimeSamples));
+ jlongArray eventTimeNanoSampleArray = jlongArray(env->GetObjectField(eventObj,
+ gMotionEventClassInfo.mEventTimeNanoSamples));
jint* pointerIdentifiers = (jint*)env->GetPrimitiveArrayCritical(pointerIdentifierArray, NULL);
jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL);
- jlong* timeSamples = (jlong*)env->GetPrimitiveArrayCritical(timeSampleArray, NULL);
+ jlong* eventTimeNanoSamples = (jlong*)env->GetPrimitiveArrayCritical(
+ eventTimeNanoSampleArray, NULL);
+ const int32_t* srcPointerIdentifiers = event->getPointerIds();
+ jint* destPointerIdentifiers = pointerIdentifiers;
for (jint i = 0; i < numPointers; i++) {
- pointerIdentifiers[i] = event->getPointerId(i);
+ *(destPointerIdentifiers++) = *(srcPointerIdentifiers++);
}
- // Most recent data is in first slot of the DVM array, followed by the oldest,
- // and then all others are in order.
-
- jfloat* currentDataSample = dataSamples;
- jlong* currentTimeSample = timeSamples;
-
- *(currentTimeSample++) = nanoseconds_to_milliseconds(event->getEventTime());
- for (jint j = 0; j < numPointers; j++) {
- *(currentDataSample++) = event->getX(j);
- *(currentDataSample++) = event->getY(j);
- *(currentDataSample++) = event->getPressure(j);
- *(currentDataSample++) = event->getSize(j);
+ const nsecs_t* srcSampleEventTimes = event->getSampleEventTimes();
+ jlong* destEventTimeNanoSamples = eventTimeNanoSamples;
+ for (jint i = 0; i < numSamples; i++) {
+ *(destEventTimeNanoSamples++) = *(srcSampleEventTimes++);
}
- for (jint i = 0; i < numHistoricalSamples; i++) {
- *(currentTimeSample++) = nanoseconds_to_milliseconds(event->getHistoricalEventTime(i));
- for (jint j = 0; j < numPointers; j++) {
- *(currentDataSample++) = event->getHistoricalX(j, i);
- *(currentDataSample++) = event->getHistoricalY(j, i);
- *(currentDataSample++) = event->getHistoricalPressure(j, i);
- *(currentDataSample++) = event->getHistoricalSize(j, i);
- }
+ const PointerCoords* srcSamplePointerCoords = event->getSamplePointerCoords();
+ jfloat* destDataSamples = dataSamples;
+ jint numItems = numSamples * numPointers;
+ for (jint i = 0; i < numItems; i++) {
+ *(destDataSamples++) = srcSamplePointerCoords->x;
+ *(destDataSamples++) = srcSamplePointerCoords->y;
+ *(destDataSamples++) = srcSamplePointerCoords->pressure;
+ *(destDataSamples++) = srcSamplePointerCoords->size;
+ srcSamplePointerCoords += 1;
}
env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, 0);
env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, 0);
- env->ReleasePrimitiveArrayCritical(timeSampleArray, timeSamples, 0);
+ env->ReleasePrimitiveArrayCritical(eventTimeNanoSampleArray, eventTimeNanoSamples, 0);
env->DeleteLocalRef(pointerIdentifierArray);
env->DeleteLocalRef(dataSampleArray);
- env->DeleteLocalRef(timeSampleArray);
+ env->DeleteLocalRef(eventTimeNanoSampleArray);
return eventObj;
}
void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, int32_t nature,
MotionEvent* event) {
- // MotionEvent.mEventTimeNano is the time of the oldest sample because
- // MotionEvent.addBatch does not update it as successive samples are added.
- jlong downTime = env->GetLongField(eventObj, gMotionEventClassInfo.mDownTime);
- jlong eventTimeNano = env->GetLongField(eventObj, gMotionEventClassInfo.mEventTimeNano);
+ jlong downTimeNano = env->GetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano);
jint action = env->GetIntField(eventObj, gMotionEventClassInfo.mAction);
- jfloat rawX = env->GetFloatField(eventObj, gMotionEventClassInfo.mRawX);
- jfloat rawY = env->GetFloatField(eventObj, gMotionEventClassInfo.mRawY);
+ jfloat xOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mXOffset);
+ jfloat yOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mYOffset);
jfloat xPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mXPrecision);
jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision);
jint deviceId = env->GetIntField(eventObj, gMotionEventClassInfo.mDeviceId);
@@ -169,72 +159,51 @@
gMotionEventClassInfo.mPointerIdentifiers));
jfloatArray dataSampleArray = jfloatArray(env->GetObjectField(eventObj,
gMotionEventClassInfo.mDataSamples));
- jlongArray timeSampleArray = jlongArray(env->GetObjectField(eventObj,
- gMotionEventClassInfo.mTimeSamples));
+ jlongArray eventTimeNanoSampleArray = jlongArray(env->GetObjectField(eventObj,
+ gMotionEventClassInfo.mEventTimeNanoSamples));
LOG_FATAL_IF(numPointers == 0, "numPointers was zero");
LOG_FATAL_IF(numSamples == 0, "numSamples was zero");
jint* pointerIdentifiers = (jint*)env->GetPrimitiveArrayCritical(pointerIdentifierArray, NULL);
jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL);
- jlong* timeSamples = (jlong*)env->GetPrimitiveArrayCritical(timeSampleArray, NULL);
+ jlong* eventTimeNanoSamples = (jlong*)env->GetPrimitiveArrayCritical(
+ eventTimeNanoSampleArray, NULL);
- // Most recent data is in first slot of the DVM array, followed by the oldest,
- // and then all others are in order. eventTimeNano is the time of the oldest sample
- // since MotionEvent.addBatch does not update it.
+ jfloat* srcDataSamples = dataSamples;
+ jlong* srcEventTimeNanoSamples = eventTimeNanoSamples;
- jint numHistoricalSamples = numSamples - 1;
- jint dataSampleStride = numPointers * NUM_SAMPLE_DATA;
-
- const jfloat* currentDataSample;
- const jlong* currentTimeSample;
- if (numHistoricalSamples == 0) {
- currentDataSample = dataSamples;
- currentTimeSample = timeSamples;
- } else {
- currentDataSample = dataSamples + dataSampleStride;
- currentTimeSample = timeSamples + 1;
- }
-
- PointerCoords pointerCoords[MAX_POINTERS];
+ jlong sampleEventTime = *(srcEventTimeNanoSamples++);
+ PointerCoords samplePointerCoords[MAX_POINTERS];
for (jint j = 0; j < numPointers; j++) {
- pointerCoords[j].x = *(currentDataSample++);
- pointerCoords[j].y = *(currentDataSample++);
- pointerCoords[j].pressure = *(currentDataSample++);
- pointerCoords[j].size = *(currentDataSample++);
+ samplePointerCoords[j].x = *(srcDataSamples++);
+ samplePointerCoords[j].y = *(srcDataSamples++);
+ samplePointerCoords[j].pressure = *(srcDataSamples++);
+ samplePointerCoords[j].size = *(srcDataSamples++);
}
event->initialize(deviceId, nature, action, edgeFlags, metaState,
- rawX, rawY, xPrecision, yPrecision,
- milliseconds_to_nanoseconds(downTime), eventTimeNano,
- numPointers, pointerIdentifiers, pointerCoords);
+ xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime,
+ numPointers, pointerIdentifiers, samplePointerCoords);
- while (numHistoricalSamples > 0) {
- numHistoricalSamples -= 1;
- if (numHistoricalSamples == 0) {
- currentDataSample = dataSamples;
- currentTimeSample = timeSamples;
- }
-
- nsecs_t sampleEventTime = milliseconds_to_nanoseconds(*(currentTimeSample++));
-
+ for (jint i = 1; i < numSamples; i++) {
+ sampleEventTime = *(srcEventTimeNanoSamples++);
for (jint j = 0; j < numPointers; j++) {
- pointerCoords[j].x = *(currentDataSample++);
- pointerCoords[j].y = *(currentDataSample++);
- pointerCoords[j].pressure = *(currentDataSample++);
- pointerCoords[j].size = *(currentDataSample++);
+ samplePointerCoords[j].x = *(srcDataSamples++);
+ samplePointerCoords[j].y = *(srcDataSamples++);
+ samplePointerCoords[j].pressure = *(srcDataSamples++);
+ samplePointerCoords[j].size = *(srcDataSamples++);
}
-
- event->addSample(sampleEventTime, pointerCoords);
+ event->addSample(sampleEventTime, samplePointerCoords);
}
env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, JNI_ABORT);
env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, JNI_ABORT);
- env->ReleasePrimitiveArrayCritical(timeSampleArray, timeSamples, JNI_ABORT);
+ env->ReleasePrimitiveArrayCritical(eventTimeNanoSampleArray, eventTimeNanoSamples, JNI_ABORT);
env->DeleteLocalRef(pointerIdentifierArray);
env->DeleteLocalRef(dataSampleArray);
- env->DeleteLocalRef(timeSampleArray);
+ env->DeleteLocalRef(eventTimeNanoSampleArray);
}
void android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
@@ -273,16 +242,14 @@
GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
"recycle", "()V");
- GET_FIELD_ID(gMotionEventClassInfo.mDownTime, gMotionEventClassInfo.clazz,
- "mDownTime", "J");
- GET_FIELD_ID(gMotionEventClassInfo.mEventTimeNano, gMotionEventClassInfo.clazz,
- "mEventTimeNano", "J");
+ GET_FIELD_ID(gMotionEventClassInfo.mDownTimeNano, gMotionEventClassInfo.clazz,
+ "mDownTimeNano", "J");
GET_FIELD_ID(gMotionEventClassInfo.mAction, gMotionEventClassInfo.clazz,
"mAction", "I");
- GET_FIELD_ID(gMotionEventClassInfo.mRawX, gMotionEventClassInfo.clazz,
- "mRawX", "F");
- GET_FIELD_ID(gMotionEventClassInfo.mRawY, gMotionEventClassInfo.clazz,
- "mRawY", "F");
+ GET_FIELD_ID(gMotionEventClassInfo.mXOffset, gMotionEventClassInfo.clazz,
+ "mXOffset", "F");
+ GET_FIELD_ID(gMotionEventClassInfo.mYOffset, gMotionEventClassInfo.clazz,
+ "mYOffset", "F");
GET_FIELD_ID(gMotionEventClassInfo.mXPrecision, gMotionEventClassInfo.clazz,
"mXPrecision", "F");
GET_FIELD_ID(gMotionEventClassInfo.mYPrecision, gMotionEventClassInfo.clazz,
@@ -301,8 +268,12 @@
"mPointerIdentifiers", "[I");
GET_FIELD_ID(gMotionEventClassInfo.mDataSamples, gMotionEventClassInfo.clazz,
"mDataSamples", "[F");
- GET_FIELD_ID(gMotionEventClassInfo.mTimeSamples, gMotionEventClassInfo.clazz,
- "mTimeSamples", "[J");
+ GET_FIELD_ID(gMotionEventClassInfo.mEventTimeNanoSamples, gMotionEventClassInfo.clazz,
+ "mEventTimeNanoSamples", "[J");
+ GET_FIELD_ID(gMotionEventClassInfo.mLastDataSampleIndex, gMotionEventClassInfo.clazz,
+ "mLastDataSampleIndex", "I");
+ GET_FIELD_ID(gMotionEventClassInfo.mLastEventTimeNanoSampleIndex, gMotionEventClassInfo.clazz,
+ "mLastEventTimeNanoSampleIndex", "I");
return 0;
}
diff --git a/include/ui/Input.h b/include/ui/Input.h
index d45bfcf..92ff872 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -148,6 +148,9 @@
int32_t mNature;
};
+/*
+ * Key events.
+ */
class KeyEvent : public InputEvent {
public:
virtual ~KeyEvent() { }
@@ -193,6 +196,9 @@
nsecs_t mEventTime;
};
+/*
+ * Motion events.
+ */
class MotionEvent : public InputEvent {
public:
virtual ~MotionEvent() { }
@@ -205,6 +211,10 @@
inline int32_t getMetaState() const { return mMetaState; }
+ inline float getXOffset() const { return mXOffset; }
+
+ inline float getYOffset() const { return mYOffset; }
+
inline float getXPrecision() const { return mXPrecision; }
inline float getYPrecision() const { return mYPrecision; }
@@ -217,18 +227,22 @@
inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
- inline float getRawX() const { return mRawX; }
-
- inline float getRawY() const { return mRawY; }
-
- inline float getX(size_t pointerIndex) const {
+ inline float getRawX(size_t pointerIndex) const {
return getCurrentPointerCoords(pointerIndex).x;
}
- inline float getY(size_t pointerIndex) const {
+ inline float getRawY(size_t pointerIndex) const {
return getCurrentPointerCoords(pointerIndex).y;
}
+ inline float getX(size_t pointerIndex) const {
+ return getRawX(pointerIndex) + mXOffset;
+ }
+
+ inline float getY(size_t pointerIndex) const {
+ return getRawY(pointerIndex) + mYOffset;
+ }
+
inline float getPressure(size_t pointerIndex) const {
return getCurrentPointerCoords(pointerIndex).pressure;
}
@@ -243,14 +257,22 @@
return mSampleEventTimes[historicalIndex];
}
- inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
+ inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const {
return getHistoricalPointerCoords(pointerIndex, historicalIndex).x;
}
- inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
+ inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const {
return getHistoricalPointerCoords(pointerIndex, historicalIndex).y;
}
+ inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalRawX(pointerIndex, historicalIndex) + mXOffset;
+ }
+
+ inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalRawY(pointerIndex, historicalIndex) + mYOffset;
+ }
+
inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const {
return getHistoricalPointerCoords(pointerIndex, historicalIndex).pressure;
}
@@ -265,8 +287,8 @@
int32_t action,
int32_t edgeFlags,
int32_t metaState,
- float rawX,
- float rawY,
+ float xOffset,
+ float yOffset,
float xPrecision,
float yPrecision,
nsecs_t downTime,
@@ -281,12 +303,19 @@
void offsetLocation(float xOffset, float yOffset);
+ // Low-level accessors.
+ inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
+ inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
+ inline const PointerCoords* getSamplePointerCoords() const {
+ return mSamplePointerCoords.array();
+ }
+
private:
int32_t mAction;
int32_t mEdgeFlags;
int32_t mMetaState;
- float mRawX;
- float mRawY;
+ float mXOffset;
+ float mYOffset;
float mXPrecision;
float mYPrecision;
nsecs_t mDownTime;
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 9537523..7b182f3 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -62,7 +62,7 @@
* Returns OK on success.
*/
static status_t openInputChannelPair(const String8& name,
- InputChannel** outServerChannel, InputChannel** outClientChannel);
+ sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
inline String8 getName() const { return mName; }
inline int32_t getAshmemFd() const { return mAshmemFd; }
@@ -72,7 +72,8 @@
/* Sends a signal to the other endpoint.
*
* Returns OK on success.
- * Errors probably indicate that the channel is broken.
+ * Returns DEAD_OBJECT if the channel's peer has been closed.
+ * Other errors probably indicate that the channel is broken.
*/
status_t sendSignal(char signal);
@@ -81,6 +82,7 @@
*
* Returns OK on success.
* Returns WOULD_BLOCK if there is no signal present.
+ * Returns DEAD_OBJECT if the channel's peer has been closed.
* Other errors probably indicate that the channel is broken.
*/
status_t receiveSignal(char* outSignal);
@@ -298,7 +300,7 @@
* Returns INVALID_OPERATION if there is no currently published event.
* Returns NO_MEMORY if the event could not be created.
*/
- status_t consume(InputEventFactoryInterface* factory, InputEvent** event);
+ status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent);
/* Sends a finished signal to the publisher to inform it that the current message is
* finished processing.
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
index c9d951f..a95fb17 100644
--- a/include/utils/PollLoop.h
+++ b/include/utils/PollLoop.h
@@ -114,8 +114,10 @@
};
Mutex mLock;
- Condition mAwake;
bool mPolling;
+ uint32_t mWaiters;
+ Condition mAwake;
+ Condition mResume;
int mWakeReadPipeFd;
int mWakeWritePipeFd;
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index d40ae16..ec851bd 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -115,10 +115,10 @@
//! insert an array at a given index
- ssize_t insertArrayAt(const TYPE* array, size_t index, size_t numItems);
+ ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
- ssize_t appendArray(const TYPE* array, size_t numItems);
+ ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
@@ -126,7 +126,7 @@
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
- //! insert on onr several items initialized from a prototype item
+ //! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
@@ -265,13 +265,13 @@
}
template<class TYPE> inline
-ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t numItems) {
- return VectorImpl::insertAt(array, index, numItems);
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
+ return VectorImpl::insertArrayAt(array, index, length);
}
template<class TYPE> inline
-ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t numItems) {
- return VectorImpl::add(array, numItems);
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
+ return VectorImpl::appendArray(array, length);
}
template<class TYPE> inline
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 46a7bc2..c4ec2ff 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -65,9 +65,11 @@
size_t capacity() const;
ssize_t setCapacity(size_t size);
- /*! append/insert another vector */
+ /*! append/insert another vector or array */
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t length);
+ ssize_t appendArray(const void* array, size_t length);
/*! add/insert/replace items */
ssize_t insertAt(size_t where, size_t numItems = 1);
@@ -76,7 +78,7 @@
void push();
void push(const void* item);
ssize_t add();
- ssize_t add(const void* item, size_t numItems = 1);
+ ssize_t add(const void* item);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
@@ -184,8 +186,8 @@
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
- ssize_t insertArrayAt(const void* array, size_t index, size_t numItems);
- ssize_t appendArray(const void* array, size_t numItems);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t length);
+ ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index d367708..0e6f2f5 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -50,8 +50,8 @@
int32_t action,
int32_t edgeFlags,
int32_t metaState,
- float rawX,
- float rawY,
+ float xOffset,
+ float yOffset,
float xPrecision,
float yPrecision,
nsecs_t downTime,
@@ -63,8 +63,8 @@
mAction = action;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
- mRawX = rawX;
- mRawY = rawY;
+ mXOffset = xOffset;
+ mYOffset = yOffset;
mXPrecision = xPrecision;
mYPrecision = yPrecision;
mDownTime = downTime;
@@ -83,13 +83,8 @@
}
void MotionEvent::offsetLocation(float xOffset, float yOffset) {
- if (xOffset != 0 || yOffset != 0) {
- for (size_t i = 0; i < mSamplePointerCoords.size(); i++) {
- PointerCoords& pointerCoords = mSamplePointerCoords.editItemAt(i);
- pointerCoords.x += xOffset;
- pointerCoords.y += yOffset;
- }
- }
+ mXOffset += xOffset;
+ mYOffset += yOffset;
}
} // namespace android
@@ -163,6 +158,14 @@
return reinterpret_cast<const MotionEvent*>(motion_event)->getEventTime();
}
+float motion_event_get_x_offset(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getXOffset();
+}
+
+float motion_event_get_y_offset(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getYOffset();
+}
+
float motion_event_get_x_precision(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getXPrecision();
}
@@ -179,12 +182,12 @@
return reinterpret_cast<const MotionEvent*>(motion_event)->getPointerId(pointer_index);
}
-float motion_event_get_raw_x(const input_event_t* motion_event) {
- return reinterpret_cast<const MotionEvent*>(motion_event)->getRawX();
+float motion_event_get_raw_x(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getRawX(pointer_index);
}
-float motion_event_get_raw_y(const input_event_t* motion_event) {
- return reinterpret_cast<const MotionEvent*>(motion_event)->getRawY();
+float motion_event_get_raw_y(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getRawY(pointer_index);
}
float motion_event_get_x(const input_event_t* motion_event, size_t pointer_index) {
@@ -213,6 +216,18 @@
history_index);
}
+float motion_event_get_historical_raw_x(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalRawX(
+ pointer_index, history_index);
+}
+
+float motion_event_get_historical_raw_y(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalRawY(
+ pointer_index, history_index);
+}
+
float motion_event_get_historical_x(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalX(
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index f058271..14dcada 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -379,8 +379,7 @@
mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
entry->edgeFlags, entry->metaState,
- entry->firstSample.pointerCoords[0].x, entry->firstSample.pointerCoords[0].y,
- entry->xPrecision, entry->yPrecision,
+ 0, 0, entry->xPrecision, entry->yPrecision,
entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
entry->firstSample.pointerCoords);
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 62b5f288..5a280ae 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -19,6 +19,9 @@
// Log debug messages about pointers.
#define DEBUG_POINTERS 1
+// Log debug messages about pointer assignment calculations.
+#define DEBUG_POINTER_ASSIGNMENT 0
+
#include <cutils/log.h>
#include <ui/InputReader.h>
@@ -57,6 +60,14 @@
return a < b ? a : b;
}
+template<typename T>
+inline static void swap(T& a, T& b) {
+ T temp = a;
+ a = b;
+ b = temp;
+}
+
+
int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
int32_t mask;
switch (keyCode) {
@@ -188,6 +199,12 @@
jumpyTouchFilter.jumpyPointsDropped = 0;
}
+struct PointerDistanceHeapElement {
+ uint32_t currentPointerIndex : 8;
+ uint32_t lastPointerIndex : 8;
+ uint64_t distance : 48; // squared distance
+};
+
void InputDevice::TouchScreenState::calculatePointerIds() {
uint32_t currentPointerCount = currentTouch.pointerCount;
uint32_t lastPointerCount = lastTouch.pointerCount;
@@ -214,11 +231,7 @@
// We build a heap of squared euclidean distances between current and last pointers
// associated with the current and last pointer indices. Then, we find the best
// match (by distance) for each current pointer.
- struct {
- uint32_t currentPointerIndex : 8;
- uint32_t lastPointerIndex : 8;
- uint64_t distance : 48; // squared distance
- } heap[MAX_POINTERS * MAX_POINTERS];
+ PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
uint32_t heapSize = 0;
for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
@@ -233,23 +246,45 @@
uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
// Insert new element into the heap (sift up).
+ heap[heapSize].currentPointerIndex = currentPointerIndex;
+ heap[heapSize].lastPointerIndex = lastPointerIndex;
+ heap[heapSize].distance = distance;
heapSize += 1;
- uint32_t insertionIndex = heapSize;
- while (insertionIndex > 1) {
- uint32_t parentIndex = (insertionIndex - 1) / 2;
- if (distance < heap[parentIndex].distance) {
- heap[insertionIndex] = heap[parentIndex];
- insertionIndex = parentIndex;
- } else {
- break;
- }
- }
- heap[insertionIndex].currentPointerIndex = currentPointerIndex;
- heap[insertionIndex].lastPointerIndex = lastPointerIndex;
- heap[insertionIndex].distance = distance;
}
}
+ // Heapify
+ for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
+ startIndex -= 1;
+ for (uint32_t parentIndex = startIndex; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
+ break;
+ }
+
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
+ }
+ }
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
+
// Pull matches out by increasing order of distance.
// To avoid reassigning pointers that have already been matched, the loop keeps track
// of which last and current pointers have been matched using the matchedXXXBits variables.
@@ -262,7 +297,7 @@
for (;;) {
if (first) {
// The first time through the loop, we just consume the root element of
- // the heap (the one with smalled distance).
+ // the heap (the one with smallest distance).
first = false;
} else {
// Previous iterations consumed the root element of the heap.
@@ -270,10 +305,10 @@
heapSize -= 1;
assert(heapSize > 0);
- // Sift down to find where the element at index heapSize needs to be moved.
- uint32_t rootIndex = 0;
- for (;;) {
- uint32_t childIndex = rootIndex * 2 + 1;
+ // Sift down.
+ heap[0] = heap[heapSize];
+ for (uint32_t parentIndex = 0; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
if (childIndex >= heapSize) {
break;
}
@@ -283,14 +318,22 @@
childIndex += 1;
}
- if (heap[heapSize].distance < heap[childIndex].distance) {
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
break;
}
- heap[rootIndex] = heap[childIndex];
- rootIndex = childIndex;
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
}
- heap[rootIndex] = heap[heapSize];
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
}
uint32_t currentPointerIndex = heap[0].currentPointerIndex;
@@ -306,6 +349,11 @@
currentTouch.pointers[currentPointerIndex].id = id;
currentTouch.idToIndex[id] = currentPointerIndex;
usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
+ lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+#endif
break;
}
}
@@ -320,6 +368,11 @@
currentTouch.idToIndex[id] = currentPointerIndex;
usedIdBits.markBit(id);
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
+ currentPointerIndex, id);
+#endif
+
if (--i == 0) break; // done
matchedCurrentBits.markBit(currentPointerIndex);
}
@@ -1208,8 +1261,10 @@
int32_t x = device->touchScreen.currentTouch.pointers[0].x;
int32_t y = device->touchScreen.currentTouch.pointers[0].y;
- if (device->touchScreen.isPointInsideDisplay(x, y)) {
- // Pointer moved inside the display area. Send key cancellation.
+ if (device->touchScreen.isPointInsideDisplay(x, y)
+ || device->touchScreen.currentTouch.pointerCount != 1) {
+ // Pointer moved inside the display area or another pointer also went down.
+ // Send key cancellation.
device->touchScreen.currentVirtualKey.down = false;
#if DEBUG_VIRTUAL_KEYS
@@ -1227,7 +1282,7 @@
device->touchScreen.lastTouch.clear();
return false; // not consumed
}
- } else if (device->touchScreen.currentTouch.pointerCount > 0
+ } else if (device->touchScreen.currentTouch.pointerCount == 1
&& device->touchScreen.lastTouch.pointerCount == 0) {
int32_t x = device->touchScreen.currentTouch.pointers[0].x;
int32_t y = device->touchScreen.currentTouch.pointers[0].y;
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index a24180f..86bbd37 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -8,13 +8,13 @@
//#define LOG_NDEBUG 0
// Log debug messages about channel signalling (send signal, receive signal)
-#define DEBUG_CHANNEL_SIGNALS 1
+#define DEBUG_CHANNEL_SIGNALS 0
// Log debug messages whenever InputChannel objects are created/destroyed
-#define DEBUG_CHANNEL_LIFECYCLE 1
+#define DEBUG_CHANNEL_LIFECYCLE 0
// Log debug messages about transport actions (initialize, reset, publish, ...)
-#define DEBUG_TRANSPORT_ACTIONS 1
+#define DEBUG_TRANSPORT_ACTIONS 0
#include <cutils/ashmem.h>
@@ -70,7 +70,7 @@
}
status_t InputChannel::openInputChannelPair(const String8& name,
- InputChannel** outServerChannel, InputChannel** outClientChannel) {
+ sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
status_t result;
int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
@@ -107,12 +107,12 @@
} else {
String8 serverChannelName = name;
serverChannelName.append(" (server)");
- *outServerChannel = new InputChannel(serverChannelName,
+ outServerChannel = new InputChannel(serverChannelName,
serverAshmemFd, reverse[0], forward[1]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
- *outClientChannel = new InputChannel(clientChannelName,
+ outClientChannel = new InputChannel(clientChannelName,
clientAshmemFd, forward[0], reverse[1]);
return OK;
}
@@ -125,8 +125,8 @@
::close(serverAshmemFd);
}
- *outServerChannel = NULL;
- *outClientChannel = NULL;
+ outServerChannel.clear();
+ outClientChannel.clear();
return result;
}
@@ -155,6 +155,13 @@
return OK;
}
+ if (nRead == 0) { // check for EOF
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string());
+#endif
+ return DEAD_OBJECT;
+ }
+
if (errno == EAGAIN) {
#if DEBUG_CHANNEL_SIGNALS
LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
@@ -535,13 +542,13 @@
return OK;
}
-status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** event) {
+status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' consumer ~ consume",
mChannel->getName().string());
#endif
- *event = NULL;
+ *outEvent = NULL;
int ashmemFd = mChannel->getAshmemFd();
int result = ashmem_pin_region(ashmemFd, 0, 0);
@@ -583,7 +590,7 @@
populateKeyEvent(keyEvent);
- *event = keyEvent;
+ *outEvent = keyEvent;
break;
}
@@ -593,7 +600,7 @@
populateMotionEvent(motionEvent);
- *event = motionEvent;
+ *outEvent = motionEvent;
break;
}
@@ -655,8 +662,8 @@
mSharedMessage->motion.action,
mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState,
- mSharedMessage->motion.sampleData[0].coords[0].x,
- mSharedMessage->motion.sampleData[0].coords[0].y,
+ mSharedMessage->motion.xOffset,
+ mSharedMessage->motion.yOffset,
mSharedMessage->motion.xPrecision,
mSharedMessage->motion.yPrecision,
mSharedMessage->motion.downTime,
@@ -676,9 +683,6 @@
motionEvent->addSample(sampleData->eventTime, sampleData->coords);
}
}
-
- motionEvent->offsetLocation(mSharedMessage->motion.xOffset,
- mSharedMessage->motion.yOffset);
}
} // namespace android
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 1ff896b..46d7493 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -3,7 +3,9 @@
include $(CLEAR_VARS)
test_src_files := \
- InputDispatcher_test.cpp
+ InputChannel_test.cpp \
+ InputDispatcher_test.cpp \
+ InputPublisherAndConsumer_test.cpp
shared_libraries := \
libcutils \
diff --git a/libs/ui/tests/InputChannel_test.cpp b/libs/ui/tests/InputChannel_test.cpp
new file mode 100644
index 0000000..6cec1c0
--- /dev/null
+++ b/libs/ui/tests/InputChannel_test.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <ui/InputTransport.h>
+#include <utils/Timers.h>
+#include <utils/StopWatch.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/mman.h>
+#include <cutils/ashmem.h>
+
+#include "../../utils/tests/TestHelpers.h"
+
+namespace android {
+
+class InputChannelTest : public testing::Test {
+protected:
+ virtual void SetUp() { }
+ virtual void TearDown() { }
+};
+
+
+TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptors) {
+ // Our purpose here is to verify that the input channel destructor closes the
+ // file descriptors provided to it. One easy way is to provide it with one end
+ // of a pipe and to check for EPIPE on the other end after the channel is destroyed.
+ Pipe fakeAshmem, sendPipe, receivePipe;
+
+ sp<InputChannel> inputChannel = new InputChannel(String8("channel name"),
+ fakeAshmem.sendFd, receivePipe.receiveFd, sendPipe.sendFd);
+
+ EXPECT_STREQ("channel name", inputChannel->getName().string())
+ << "channel should have provided name";
+ EXPECT_EQ(fakeAshmem.sendFd, inputChannel->getAshmemFd())
+ << "channel should have provided ashmem fd";
+ EXPECT_EQ(receivePipe.receiveFd, inputChannel->getReceivePipeFd())
+ << "channel should have provided receive pipe fd";
+ EXPECT_EQ(sendPipe.sendFd, inputChannel->getSendPipeFd())
+ << "channel should have provided send pipe fd";
+
+ inputChannel.clear(); // destroys input channel
+
+ EXPECT_EQ(-EPIPE, fakeAshmem.readSignal())
+ << "channel should have closed ashmem fd when destroyed";
+ EXPECT_EQ(-EPIPE, receivePipe.writeSignal())
+ << "channel should have closed receive pipe fd when destroyed";
+ EXPECT_EQ(-EPIPE, sendPipe.readSignal())
+ << "channel should have closed send pipe fd when destroyed";
+
+ // clean up fds of Pipe endpoints that were closed so we don't try to close them again
+ fakeAshmem.sendFd = -1;
+ receivePipe.receiveFd = -1;
+ sendPipe.sendFd = -1;
+}
+
+TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ status_t result = InputChannel::openInputChannelPair(String8("channel name"),
+ serverChannel, clientChannel);
+
+ ASSERT_EQ(OK, result)
+ << "should have successfully opened a channel pair";
+
+ // Name
+ EXPECT_STREQ("channel name (server)", serverChannel->getName().string())
+ << "server channel should have suffixed name";
+ EXPECT_STREQ("channel name (client)", clientChannel->getName().string())
+ << "client channel should have suffixed name";
+
+ // Ashmem uniqueness
+ EXPECT_NE(serverChannel->getAshmemFd(), clientChannel->getAshmemFd())
+ << "server and client channel should have different ashmem fds because it was dup'd";
+
+ // Ashmem usability
+ ssize_t serverAshmemSize = ashmem_get_size_region(serverChannel->getAshmemFd());
+ ssize_t clientAshmemSize = ashmem_get_size_region(clientChannel->getAshmemFd());
+ uint32_t* serverAshmem = static_cast<uint32_t*>(mmap(NULL, serverAshmemSize,
+ PROT_READ | PROT_WRITE, MAP_SHARED, serverChannel->getAshmemFd(), 0));
+ uint32_t* clientAshmem = static_cast<uint32_t*>(mmap(NULL, clientAshmemSize,
+ PROT_READ | PROT_WRITE, MAP_SHARED, clientChannel->getAshmemFd(), 0));
+ ASSERT_TRUE(serverAshmem != NULL)
+ << "server channel ashmem should be mappable";
+ ASSERT_TRUE(clientAshmem != NULL)
+ << "client channel ashmem should be mappable";
+ *serverAshmem = 0xf00dd00d;
+ EXPECT_EQ(0xf00dd00d, *clientAshmem)
+ << "ashmem buffer should be shared by client and server";
+ munmap(serverAshmem, serverAshmemSize);
+ munmap(clientAshmem, clientAshmemSize);
+
+ // Server->Client communication
+ EXPECT_EQ(OK, serverChannel->sendSignal('S'))
+ << "server channel should be able to send signal to client channel";
+ char signal;
+ EXPECT_EQ(OK, clientChannel->receiveSignal(& signal))
+ << "client channel should be able to receive signal from server channel";
+ EXPECT_EQ('S', signal)
+ << "client channel should receive the correct signal from server channel";
+
+ // Client->Server communication
+ EXPECT_EQ(OK, clientChannel->sendSignal('c'))
+ << "client channel should be able to send signal to server channel";
+ EXPECT_EQ(OK, serverChannel->receiveSignal(& signal))
+ << "server channel should be able to receive signal from client channel";
+ EXPECT_EQ('c', signal)
+ << "server channel should receive the correct signal from client channel";
+}
+
+TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ status_t result = InputChannel::openInputChannelPair(String8("channel name"),
+ serverChannel, clientChannel);
+
+ ASSERT_EQ(OK, result)
+ << "should have successfully opened a channel pair";
+
+ char signal;
+ EXPECT_EQ(WOULD_BLOCK, clientChannel->receiveSignal(& signal))
+ << "receiveSignal should have returned WOULD_BLOCK";
+}
+
+TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ status_t result = InputChannel::openInputChannelPair(String8("channel name"),
+ serverChannel, clientChannel);
+
+ ASSERT_EQ(OK, result)
+ << "should have successfully opened a channel pair";
+
+ serverChannel.clear(); // close server channel
+
+ char signal;
+ EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveSignal(& signal))
+ << "receiveSignal should have returned DEAD_OBJECT";
+}
+
+TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ status_t result = InputChannel::openInputChannelPair(String8("channel name"),
+ serverChannel, clientChannel);
+
+ ASSERT_EQ(OK, result)
+ << "should have successfully opened a channel pair";
+
+ serverChannel.clear(); // close server channel
+
+ EXPECT_EQ(DEAD_OBJECT, clientChannel->sendSignal('S'))
+ << "sendSignal should have returned DEAD_OBJECT";
+}
+
+
+} // namespace android
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
index 3d92043..1dc6e46 100644
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ b/libs/ui/tests/InputDispatcher_test.cpp
@@ -12,8 +12,7 @@
};
TEST_F(InputDispatcherTest, Dummy) {
- SCOPED_TRACE("Trace");
- ASSERT_FALSE(true);
+ // TODO
}
} // namespace android
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
new file mode 100644
index 0000000..2d6b531
--- /dev/null
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -0,0 +1,449 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <ui/InputTransport.h>
+#include <utils/Timers.h>
+#include <utils/StopWatch.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/mman.h>
+#include <cutils/ashmem.h>
+
+#include "../../utils/tests/TestHelpers.h"
+
+namespace android {
+
+class InputPublisherAndConsumerTest : public testing::Test {
+protected:
+ sp<InputChannel> serverChannel, clientChannel;
+ InputPublisher* mPublisher;
+ InputConsumer* mConsumer;
+ PreallocatedInputEventFactory mEventFactory;
+
+ virtual void SetUp() {
+ status_t result = InputChannel::openInputChannelPair(String8("channel name"),
+ serverChannel, clientChannel);
+
+ mPublisher = new InputPublisher(serverChannel);
+ mConsumer = new InputConsumer(clientChannel);
+ }
+
+ virtual void TearDown() {
+ if (mPublisher) {
+ delete mPublisher;
+ mPublisher = NULL;
+ }
+
+ if (mConsumer) {
+ delete mConsumer;
+ mConsumer = NULL;
+ }
+
+ serverChannel.clear();
+ clientChannel.clear();
+ }
+
+ void Initialize();
+ void PublishAndConsumeKeyEvent();
+ void PublishAndConsumeMotionEvent(
+ size_t samplesToAppendBeforeDispatch = 0,
+ size_t samplesToAppendAfterDispatch = 0);
+};
+
+TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) {
+ EXPECT_EQ(serverChannel.get(), mPublisher->getChannel().get());
+ EXPECT_EQ(clientChannel.get(), mConsumer->getChannel().get());
+}
+
+void InputPublisherAndConsumerTest::Initialize() {
+ status_t status;
+
+ status = mPublisher->initialize();
+ ASSERT_EQ(OK, status)
+ << "publisher initialize should return OK";
+
+ status = mConsumer->initialize();
+ ASSERT_EQ(OK, status)
+ << "consumer initialize should return OK";
+}
+
+void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
+ status_t status;
+
+ const int32_t deviceId = 1;
+ const int32_t nature = INPUT_EVENT_NATURE_KEY;
+ const int32_t action = KEY_EVENT_ACTION_DOWN;
+ const int32_t flags = KEY_EVENT_FLAG_FROM_SYSTEM;
+ const int32_t keyCode = KEYCODE_ENTER;
+ const int32_t scanCode = 13;
+ const int32_t metaState = META_ALT_LEFT_ON | META_ALT_ON;
+ const int32_t repeatCount = 1;
+ const nsecs_t downTime = 3;
+ const nsecs_t eventTime = 4;
+
+ status = mPublisher->publishKeyEvent(deviceId, nature, action, flags,
+ keyCode, scanCode, metaState, repeatCount, downTime, eventTime);
+ ASSERT_EQ(OK, status)
+ << "publisher publishKeyEvent should return OK";
+
+ status = mPublisher->sendDispatchSignal();
+ ASSERT_EQ(OK, status)
+ << "publisher sendDispatchSignal should return OK";
+
+ status = mConsumer->receiveDispatchSignal();
+ ASSERT_EQ(OK, status)
+ << "consumer receiveDispatchSignal should return OK";
+
+ InputEvent* event;
+ status = mConsumer->consume(& mEventFactory, & event);
+ ASSERT_EQ(OK, status)
+ << "consumer consume should return OK";
+
+ ASSERT_TRUE(event != NULL)
+ << "consumer should have returned non-NULL event";
+ ASSERT_EQ(INPUT_EVENT_TYPE_KEY, event->getType())
+ << "consumer should have returned a key event";
+
+ KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
+ EXPECT_EQ(deviceId, keyEvent->getDeviceId());
+ EXPECT_EQ(nature, keyEvent->getNature());
+ EXPECT_EQ(action, keyEvent->getAction());
+ EXPECT_EQ(flags, keyEvent->getFlags());
+ EXPECT_EQ(keyCode, keyEvent->getKeyCode());
+ EXPECT_EQ(scanCode, keyEvent->getScanCode());
+ EXPECT_EQ(metaState, keyEvent->getMetaState());
+ EXPECT_EQ(repeatCount, keyEvent->getRepeatCount());
+ EXPECT_EQ(downTime, keyEvent->getDownTime());
+ EXPECT_EQ(eventTime, keyEvent->getEventTime());
+
+ status = mConsumer->sendFinishedSignal();
+ ASSERT_EQ(OK, status)
+ << "consumer sendFinishedSignal should return OK";
+
+ status = mPublisher->receiveFinishedSignal();
+ ASSERT_EQ(OK, status)
+ << "publisher receiveFinishedSignal should return OK";
+
+ status = mPublisher->reset();
+ ASSERT_EQ(OK, status)
+ << "publisher reset should return OK";
+}
+
+void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
+ size_t samplesToAppendBeforeDispatch, size_t samplesToAppendAfterDispatch) {
+ status_t status;
+
+ const int32_t deviceId = 1;
+ const int32_t nature = INPUT_EVENT_NATURE_TOUCH;
+ const int32_t action = MOTION_EVENT_ACTION_MOVE;
+ const int32_t edgeFlags = MOTION_EVENT_EDGE_FLAG_TOP;
+ const int32_t metaState = META_ALT_LEFT_ON | META_ALT_ON;
+ const float xOffset = -10;
+ const float yOffset = -20;
+ const float xPrecision = 0.25;
+ const float yPrecision = 0.5;
+ const nsecs_t downTime = 3;
+ const size_t pointerCount = 3;
+ const int32_t pointerIds[pointerCount] = { 2, 0, 1 };
+
+ Vector<nsecs_t> sampleEventTimes;
+ Vector<PointerCoords> samplePointerCoords;
+
+ for (size_t i = 0; i <= samplesToAppendAfterDispatch + samplesToAppendBeforeDispatch; i++) {
+ sampleEventTimes.push(i + 10);
+ for (size_t j = 0; j < pointerCount; j++) {
+ samplePointerCoords.push();
+ samplePointerCoords.editTop().x = 100 * i + j;
+ samplePointerCoords.editTop().y = 200 * i + j;
+ samplePointerCoords.editTop().pressure = 0.5 * i + j;
+ samplePointerCoords.editTop().size = 0.7 * i + j;
+ }
+ }
+
+ status = mPublisher->publishMotionEvent(deviceId, nature, action, edgeFlags,
+ metaState, xOffset, yOffset, xPrecision, yPrecision,
+ downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
+ ASSERT_EQ(OK, status)
+ << "publisher publishMotionEvent should return OK";
+
+ for (size_t i = 0; i < samplesToAppendBeforeDispatch; i++) {
+ size_t sampleIndex = i + 1;
+ status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex],
+ samplePointerCoords.array() + sampleIndex * pointerCount);
+ ASSERT_EQ(OK, status)
+ << "publisher appendMotionEvent should return OK";
+ }
+
+ status = mPublisher->sendDispatchSignal();
+ ASSERT_EQ(OK, status)
+ << "publisher sendDispatchSignal should return OK";
+
+ for (size_t i = 0; i < samplesToAppendAfterDispatch; i++) {
+ size_t sampleIndex = i + 1 + samplesToAppendBeforeDispatch;
+ status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex],
+ samplePointerCoords.array() + sampleIndex * pointerCount);
+ ASSERT_EQ(OK, status)
+ << "publisher appendMotionEvent should return OK";
+ }
+
+ status = mConsumer->receiveDispatchSignal();
+ ASSERT_EQ(OK, status)
+ << "consumer receiveDispatchSignal should return OK";
+
+ InputEvent* event;
+ status = mConsumer->consume(& mEventFactory, & event);
+ ASSERT_EQ(OK, status)
+ << "consumer consume should return OK";
+
+ ASSERT_TRUE(event != NULL)
+ << "consumer should have returned non-NULL event";
+ ASSERT_EQ(INPUT_EVENT_TYPE_MOTION, event->getType())
+ << "consumer should have returned a motion event";
+
+ size_t lastSampleIndex = samplesToAppendBeforeDispatch + samplesToAppendAfterDispatch;
+
+ MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
+ EXPECT_EQ(deviceId, motionEvent->getDeviceId());
+ EXPECT_EQ(nature, motionEvent->getNature());
+ EXPECT_EQ(action, motionEvent->getAction());
+ EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
+ EXPECT_EQ(metaState, motionEvent->getMetaState());
+ EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
+ EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
+ EXPECT_EQ(downTime, motionEvent->getDownTime());
+ EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime());
+ EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
+ EXPECT_EQ(lastSampleIndex, motionEvent->getHistorySize());
+
+ for (size_t i = 0; i < pointerCount; i++) {
+ SCOPED_TRACE(i);
+ EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i));
+ }
+
+ for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) {
+ SCOPED_TRACE(sampleIndex);
+ EXPECT_EQ(sampleEventTimes[sampleIndex],
+ motionEvent->getHistoricalEventTime(sampleIndex));
+ for (size_t i = 0; i < pointerCount; i++) {
+ SCOPED_TRACE(i);
+ size_t offset = sampleIndex * pointerCount + i;
+ EXPECT_EQ(samplePointerCoords[offset].x,
+ motionEvent->getHistoricalRawX(i, sampleIndex));
+ EXPECT_EQ(samplePointerCoords[offset].y,
+ motionEvent->getHistoricalRawY(i, sampleIndex));
+ EXPECT_EQ(samplePointerCoords[offset].x + xOffset,
+ motionEvent->getHistoricalX(i, sampleIndex));
+ EXPECT_EQ(samplePointerCoords[offset].y + yOffset,
+ motionEvent->getHistoricalY(i, sampleIndex));
+ EXPECT_EQ(samplePointerCoords[offset].pressure,
+ motionEvent->getHistoricalPressure(i, sampleIndex));
+ EXPECT_EQ(samplePointerCoords[offset].size,
+ motionEvent->getHistoricalSize(i, sampleIndex));
+ }
+ }
+
+ SCOPED_TRACE(lastSampleIndex);
+ EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime());
+ for (size_t i = 0; i < pointerCount; i++) {
+ SCOPED_TRACE(i);
+ size_t offset = lastSampleIndex * pointerCount + i;
+ EXPECT_EQ(samplePointerCoords[offset].x, motionEvent->getRawX(i));
+ EXPECT_EQ(samplePointerCoords[offset].y, motionEvent->getRawY(i));
+ EXPECT_EQ(samplePointerCoords[offset].x + xOffset, motionEvent->getX(i));
+ EXPECT_EQ(samplePointerCoords[offset].y + yOffset, motionEvent->getY(i));
+ EXPECT_EQ(samplePointerCoords[offset].pressure, motionEvent->getPressure(i));
+ EXPECT_EQ(samplePointerCoords[offset].size, motionEvent->getSize(i));
+ }
+
+ status = mConsumer->sendFinishedSignal();
+ ASSERT_EQ(OK, status)
+ << "consumer sendFinishedSignal should return OK";
+
+ status = mPublisher->receiveFinishedSignal();
+ ASSERT_EQ(OK, status)
+ << "publisher receiveFinishedSignal should return OK";
+
+ status = mPublisher->reset();
+ ASSERT_EQ(OK, status)
+ << "publisher reset should return OK";
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) {
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_WhenNotReset_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ ASSERT_EQ(OK, status)
+ << "publisher publishKeyEvent should return OK first time";
+
+ status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ ASSERT_EQ(INVALID_OPERATION, status)
+ << "publisher publishKeyEvent should return INVALID_OPERATION because "
+ "the publisher was not reset";
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_EndToEnd) {
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = 1;
+ int32_t pointerIds[pointerCount] = { 0 };
+ PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0 } };
+
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(OK, status)
+ << "publisher publishMotionEvent should return OK";
+
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(INVALID_OPERATION, status)
+ << "publisher publishMotionEvent should return INVALID_OPERATION because ";
+ "the publisher was not reset";
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = 0;
+ int32_t pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(BAD_VALUE, status)
+ << "publisher publishMotionEvent should return BAD_VALUE";
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = MAX_POINTERS + 1;
+ int32_t pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(BAD_VALUE, status)
+ << "publisher publishMotionEvent should return BAD_VALUE";
+}
+
+TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) {
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledBeforeDispatchSignal_AppendsSamples) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(3, 0));
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledAfterDispatchSignalAndNotConsumed_AppendsSamples) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(0, 4));
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenNoMotionEventPublished_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ PointerCoords pointerCoords[1];
+ status = mPublisher->appendMotionSample(0, pointerCoords);
+ ASSERT_EQ(INVALID_OPERATION, status)
+ << "publisher appendMotionSample should return INVALID_OPERATION";
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEventIsNotAMove_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = MAX_POINTERS;
+ int32_t pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_DOWN,
+ 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(OK, status);
+
+ status = mPublisher->appendMotionSample(0, pointerCoords);
+ ASSERT_EQ(INVALID_OPERATION, status)
+ << "publisher appendMotionSample should return INVALID_OPERATION";
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = MAX_POINTERS;
+ int32_t pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_MOVE,
+ 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(OK, status);
+
+ status = mPublisher->sendDispatchSignal();
+ ASSERT_EQ(OK, status);
+
+ status = mConsumer->receiveDispatchSignal();
+ ASSERT_EQ(OK, status);
+
+ InputEvent* event;
+ status = mConsumer->consume(& mEventFactory, & event);
+ ASSERT_EQ(OK, status);
+
+ status = mPublisher->appendMotionSample(0, pointerCoords);
+ ASSERT_EQ(status_t(FAILED_TRANSACTION), status)
+ << "publisher appendMotionSample should return FAILED_TRANSACTION";
+}
+
+TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsError) {
+ status_t status;
+ ASSERT_NO_FATAL_FAILURE(Initialize());
+
+ const size_t pointerCount = MAX_POINTERS;
+ int32_t pointerIds[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(0, 0, MOTION_EVENT_ACTION_MOVE,
+ 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ ASSERT_EQ(OK, status);
+
+ for (int count = 1;; count++) {
+ ASSERT_LT(count, 100000) << "should eventually reach OOM";
+
+ status = mPublisher->appendMotionSample(0, pointerCoords);
+ if (status != OK) {
+ ASSERT_GT(count, 12) << "should be able to add at least a dozen samples";
+ ASSERT_EQ(NO_MEMORY, status)
+ << "publisher appendMotionSample should return NO_MEMORY when buffer is full";
+ break;
+ }
+ }
+
+ status = mPublisher->appendMotionSample(0, pointerCoords);
+ ASSERT_EQ(NO_MEMORY, status)
+ << "publisher appendMotionSample should return NO_MEMORY persistently until reset";
+}
+
+} // namespace android
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
index 90a3e8b..20a4d13 100644
--- a/libs/utils/PollLoop.cpp
+++ b/libs/utils/PollLoop.cpp
@@ -11,7 +11,7 @@
#define DEBUG_POLL_AND_WAKE 0
// Debugs callback registration and invocation.
-#define DEBUG_CALLBACKS 1
+#define DEBUG_CALLBACKS 0
#include <cutils/log.h>
#include <utils/PollLoop.h>
@@ -22,7 +22,7 @@
namespace android {
PollLoop::PollLoop() :
- mPolling(false) {
+ mPolling(false), mWaiters(0) {
openWakePipe();
}
@@ -68,6 +68,9 @@
bool PollLoop::pollOnce(int timeoutMillis) {
mLock.lock();
+ while (mWaiters != 0) {
+ mResume.wait(mLock);
+ }
mPolling = true;
mLock.unlock();
@@ -156,7 +159,9 @@
Done:
mLock.lock();
mPolling = false;
- mAwake.broadcast();
+ if (mWaiters != 0) {
+ mAwake.broadcast();
+ }
mLock.unlock();
if (result) {
@@ -258,10 +263,15 @@
void PollLoop::wakeAndLock() {
mLock.lock();
+ mWaiters += 1;
while (mPolling) {
wake();
mAwake.wait(mLock);
}
+ mWaiters -= 1;
+ if (mWaiters == 0) {
+ mResume.signal();
+ }
}
} // namespace android
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index b09c6ca..289c826 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -108,7 +108,7 @@
ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
{
- return insertAt(vector.arrayImpl(), index, vector.size());
+ return insertArrayAt(vector.arrayImpl(), index, vector.size());
}
ssize_t VectorImpl::appendVector(const VectorImpl& vector)
@@ -116,6 +116,22 @@
return insertVectorAt(vector, size());
}
+ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
+{
+ if (index > size())
+ return BAD_INDEX;
+ void* where = _grow(index, length);
+ if (where) {
+ _do_copy(where, array, length);
+ }
+ return where ? index : (ssize_t)NO_MEMORY;
+}
+
+ssize_t VectorImpl::appendArray(const void* array, size_t length)
+{
+ return insertArrayAt(array, size(), length);
+}
+
ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
{
return insertAt(0, index, numItems);
@@ -220,9 +236,9 @@
return add(0);
}
-ssize_t VectorImpl::add(const void* item, size_t numItems)
+ssize_t VectorImpl::add(const void* item)
{
- return insertAt(item, size(), numItems);
+ return insertAt(item, size());
}
ssize_t VectorImpl::replaceAt(size_t index)
diff --git a/libs/utils/tests/PollLoop_test.cpp b/libs/utils/tests/PollLoop_test.cpp
index 6c719c8..4848c0f 100644
--- a/libs/utils/tests/PollLoop_test.cpp
+++ b/libs/utils/tests/PollLoop_test.cpp
@@ -16,34 +16,6 @@
namespace android {
-class Pipe {
-public:
- int sendFd;
- int receiveFd;
-
- Pipe() {
- int fds[2];
- ::pipe(fds);
-
- receiveFd = fds[0];
- sendFd = fds[1];
- }
-
- ~Pipe() {
- ::close(sendFd);
- ::close(receiveFd);
- }
-
- bool writeSignal() {
- return ::write(sendFd, "*", 1) == 1;
- }
-
- bool readSignal() {
- char buf[1];
- return ::read(receiveFd, buf, 1) == 1;
- }
-};
-
class DelayedWake : public DelayedTask {
sp<PollLoop> mPollLoop;
@@ -195,7 +167,7 @@
Pipe pipe;
StubCallbackHandler handler(true);
- ASSERT_TRUE(pipe.writeSignal());
+ ASSERT_EQ(OK, pipe.writeSignal());
handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
StopWatch stopWatch("pollOnce");
@@ -243,7 +215,7 @@
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should be approx. zero";
@@ -269,7 +241,7 @@
bool result = mPollLoop->pollOnce(1000);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal signal delay";
@@ -295,7 +267,7 @@
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal timeout because FD was no longer registered";
@@ -318,7 +290,7 @@
bool result = mPollLoop->pollOnce(0);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal zero because FD was already signalled";
@@ -334,7 +306,7 @@
result = mPollLoop->pollOnce(0);
elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal zero because timeout was zero";
@@ -382,7 +354,7 @@
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
- ASSERT_TRUE(pipe.readSignal())
+ ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. zero because FD was already signalled";
diff --git a/libs/utils/tests/TestHelpers.h b/libs/utils/tests/TestHelpers.h
index e55af3c..d8e985e 100644
--- a/libs/utils/tests/TestHelpers.h
+++ b/libs/utils/tests/TestHelpers.h
@@ -21,6 +21,41 @@
namespace android {
+class Pipe {
+public:
+ int sendFd;
+ int receiveFd;
+
+ Pipe() {
+ int fds[2];
+ ::pipe(fds);
+
+ receiveFd = fds[0];
+ sendFd = fds[1];
+ }
+
+ ~Pipe() {
+ if (sendFd != -1) {
+ ::close(sendFd);
+ }
+
+ if (receiveFd != -1) {
+ ::close(receiveFd);
+ }
+ }
+
+ status_t writeSignal() {
+ ssize_t nWritten = ::write(sendFd, "*", 1);
+ return nWritten == 1 ? 0 : -errno;
+ }
+
+ status_t readSignal() {
+ char buf[1];
+ ssize_t nRead = ::read(receiveFd, buf, 1);
+ return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
+ }
+};
+
class DelayedTask : public Thread {
int mDelayMillis;
diff --git a/native/include/android/input.h b/native/include/android/input.h
index ee2f664..193cbf3cb 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -394,6 +394,18 @@
* in the java.lang.System.nanoTime() time base. */
int64_t motion_event_get_event_time(const input_event_t* motion_event);
+/* Get the X coordinate offset.
+ * For touch events on the screen, this is the delta that was added to the raw
+ * screen coordinates to adjust for the absolute position of the containing windows
+ * and views. */
+float motion_event_get_x_offset(const input_event_t* motion_event);
+
+/* Get the precision of the Y coordinates being reported.
+ * For touch events on the screen, this is the delta that was added to the raw
+ * screen coordinates to adjust for the absolute position of the containing windows
+ * and views. */
+float motion_event_get_y_offset(const input_event_t* motion_event);
+
/* Get the precision of the X coordinates being reported.
* You can multiply this number with an X coordinate sample to find the
* actual hardware value of the X coordinate. */
@@ -414,17 +426,17 @@
* going up and down since the start of the current gesture. */
int32_t motion_event_get_pointer_id(const input_event_t* motion_event, size_t pointer_index);
-/* Get the original raw X coordinate of this event. For touch
- * events on the screen, this is the original location of the event
+/* Get the original raw X coordinate of this event.
+ * For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
* and views. */
-float motion_event_get_raw_x(const input_event_t* motion_event);
+float motion_event_get_raw_x(const input_event_t* motion_event, size_t pointer_index);
-/* Get the original raw X coordinate of this event. For touch
- * events on the screen, this is the original location of the event
+/* Get the original raw X coordinate of this event.
+ * For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
* and views. */
-float motion_event_get_raw_y(const input_event_t* motion_event);
+float motion_event_get_raw_y(const input_event_t* motion_event, size_t pointer_index);
/* Get the current X coordinate of this event for the given pointer index.
* Whole numbers are pixels; the value may have a fraction for input devices
@@ -461,6 +473,24 @@
int64_t motion_event_get_historical_event_time(input_event_t* motion_event,
size_t history_index);
+/* Get the historical raw X coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise. */
+float motion_event_get_historical_raw_x(const input_event_t* motion_event, size_t pointer_index);
+
+/* Get the historical raw Y coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise. */
+float motion_event_get_historical_raw_y(const input_event_t* motion_event, size_t pointer_index);
+
/* Get the historical X coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* Whole numbers are pixels; the value may have a fraction for input devices
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index a988a96..ab3922f 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -294,9 +294,7 @@
if (wmActions & WM_ACTION_PASS_TO_USER) {
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
- }
- if (! (wmActions & WM_ACTION_PASS_TO_USER)) {
if (down && isAppSwitchKey(keyCode)) {
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
checkExceptionFromCallback(env, "notifyAppSwitchComing");
@@ -312,12 +310,18 @@
LOGD("interceptTouch - when=%lld", when);
#endif
- if (! isScreenOn()) {
- // Touch events do not wake the device.
- return InputReaderPolicyInterface::ACTION_NONE;
+ int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
+ if (isScreenOn()) {
+ // Only dispatch touch events when the device is awake.
+ actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
}
- return InputReaderPolicyInterface::ACTION_DISPATCH;
+ if (! isScreenBright()) {
+ // Brighten the screen if dimmed.
+ actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
+ }
+
+ return actions;
}
int32_t NativeInputManager::interceptTrackball(nsecs_t when,
@@ -327,12 +331,18 @@
when, buttonChanged, buttonDown, rolled);
#endif
- if (! isScreenOn()) {
- // Trackball motions and button presses do not wake the device.
- return InputReaderPolicyInterface::ACTION_NONE;
+ int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
+ if (isScreenOn()) {
+ // Only dispatch trackball events when the device is awake.
+ actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
}
- return InputReaderPolicyInterface::ACTION_DISPATCH;
+ if (! isScreenBright()) {
+ // Brighten the screen if dimmed.
+ actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
+ }
+
+ return actions;
}
int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,