diff options
-rw-r--r-- | api/11.xml | 8 | ||||
-rw-r--r-- | api/current.xml | 325 | ||||
-rwxr-xr-x | core/java/android/view/InputDevice.java | 230 | ||||
-rwxr-xr-x | core/java/android/view/InputEvent.java | 45 | ||||
-rwxr-xr-x | core/java/android/view/KeyEvent.java | 29 | ||||
-rw-r--r-- | core/java/android/view/MotionEvent.java | 1342 | ||||
-rw-r--r-- | core/jni/android_view_MotionEvent.cpp | 943 | ||||
-rw-r--r-- | include/ui/Input.h | 182 | ||||
-rw-r--r-- | libs/ui/Android.mk | 7 | ||||
-rw-r--r-- | libs/ui/Input.cpp | 297 | ||||
-rw-r--r-- | libs/ui/tests/InputPublisherAndConsumer_test.cpp | 78 | ||||
-rw-r--r-- | native/android/input.cpp | 11 | ||||
-rw-r--r-- | native/include/android/input.h | 50 | ||||
-rw-r--r-- | services/input/InputDispatcher.cpp | 41 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 61 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 39 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 4 |
17 files changed, 2529 insertions, 1163 deletions
@@ -207497,22 +207497,22 @@ </method> <method name="getDeviceId" return="int" - abstract="false" + abstract="true" native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getSource" return="int" - abstract="false" + abstract="true" native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > diff --git a/api/current.xml b/api/current.xml index 968b8ed..d5decd9 100644 --- a/api/current.xml +++ b/api/current.xml @@ -210399,7 +210399,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="rangeType" type="int"> +<parameter name="axis" type="int"> </parameter> </method> <method name="getName" @@ -210489,7 +210489,7 @@ value="8" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210500,7 +210500,7 @@ value="2" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210511,7 +210511,7 @@ value="3" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210522,7 +210522,7 @@ value="6" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210533,7 +210533,7 @@ value="7" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210544,7 +210544,7 @@ value="4" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210555,7 +210555,7 @@ value="5" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210566,7 +210566,7 @@ value="0" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210577,7 +210577,7 @@ value="1" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210856,22 +210856,22 @@ </method> <method name="getDeviceId" return="int" - abstract="false" + abstract="true" native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > </method> <method name="getSource" return="int" - abstract="false" + abstract="true" native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -211661,6 +211661,17 @@ <parameter name="c" type="int"> </parameter> </method> +<method name="getDeviceId" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getDisplayLabel" return="char" abstract="false" @@ -211834,6 +211845,17 @@ visibility="public" > </method> +<method name="getSource" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getUnicodeChar" return="int" abstract="false" @@ -212090,6 +212112,19 @@ <parameter name="metaState" type="int"> </parameter> </method> +<method name="setSource" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="source" type="int"> +</parameter> +</method> <method name="startTracking" return="void" abstract="false" @@ -216346,6 +216381,45 @@ visibility="public" > </method> +<method name="getAxisValue" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +</method> +<method name="getAxisValue" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +<parameter name="pointerIndex" type="int"> +</parameter> +</method> +<method name="getDeviceId" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getDownTime" return="long" abstract="false" @@ -216390,6 +216464,38 @@ visibility="public" > </method> +<method name="getHistoricalAxisValue" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +<parameter name="pos" type="int"> +</parameter> +</method> +<method name="getHistoricalAxisValue" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +<parameter name="pointerIndex" type="int"> +</parameter> +<parameter name="pos" type="int"> +</parameter> +</method> <method name="getHistoricalEventTime" return="long" abstract="false" @@ -216827,6 +216933,17 @@ <parameter name="pointerIndex" type="int"> </parameter> </method> +<method name="getSource" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getToolMajor" return="float" abstract="false" @@ -217135,7 +217252,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="o" type="android.view.MotionEvent"> +<parameter name="other" type="android.view.MotionEvent"> </parameter> </method> <method name="obtainNoHistory" @@ -217148,7 +217265,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="o" type="android.view.MotionEvent"> +<parameter name="other" type="android.view.MotionEvent"> </parameter> </method> <method name="offsetLocation" @@ -217218,6 +217335,19 @@ <parameter name="y" type="float"> </parameter> </method> +<method name="setSource" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="source" type="int"> +</parameter> +</method> <method name="transform" return="void" abstract="false" @@ -217444,6 +217574,105 @@ visibility="public" > </field> +<field name="AXIS_ORIENTATION" + type="int" + transient="false" + volatile="false" + value="8" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_PRESSURE" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_SIZE" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_TOOL_MAJOR" + type="int" + transient="false" + volatile="false" + value="6" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_TOOL_MINOR" + type="int" + transient="false" + volatile="false" + value="7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_TOUCH_MAJOR" + type="int" + transient="false" + volatile="false" + value="4" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_TOUCH_MINOR" + type="int" + transient="false" + volatile="false" + value="5" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_X" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="AXIS_Y" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="CREATOR" type="android.os.Parcelable.Creator" transient="false" @@ -217526,6 +217755,68 @@ visibility="public" > </constructor> +<constructor name="MotionEvent.PointerCoords" + type="android.view.MotionEvent.PointerCoords" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="other" type="android.view.MotionEvent.PointerCoords"> +</parameter> +</constructor> +<method name="clear" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="copyFrom" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="other" type="android.view.MotionEvent.PointerCoords"> +</parameter> +</method> +<method name="getAxisValue" + return="float" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +</method> +<method name="setAxisValue" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="axis" type="int"> +</parameter> +<parameter name="value" type="float"> +</parameter> +</method> <field name="orientation" type="float" transient="false" @@ -265620,7 +265911,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index e799f76..7abbce6 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.SparseArray; /** * Describes the capabilities of a particular input device. @@ -41,9 +42,9 @@ public final class InputDevice implements Parcelable { private String mName; private int mSources; private int mKeyboardType; - - private MotionRange[] mMotionRanges; - + + private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>(); + /** * A mask for input source classes. * @@ -181,70 +182,85 @@ public final class InputDevice implements Parcelable { public static final int SOURCE_ANY = 0xffffff00; /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#x}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_X} instead. */ - public static final int MOTION_RANGE_X = 0; - + @Deprecated + public static final int MOTION_RANGE_X = MotionEvent.AXIS_X; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#y}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_Y} instead. */ - public static final int MOTION_RANGE_Y = 1; - + @Deprecated + public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#pressure}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead. */ - public static final int MOTION_RANGE_PRESSURE = 2; - + @Deprecated + public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#size}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead. */ - public static final int MOTION_RANGE_SIZE = 3; - + @Deprecated + public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMajor}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead. */ - public static final int MOTION_RANGE_TOUCH_MAJOR = 4; - + @Deprecated + public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMinor}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead. */ - public static final int MOTION_RANGE_TOUCH_MINOR = 5; - + @Deprecated + public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMajor}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead. */ - public static final int MOTION_RANGE_TOOL_MAJOR = 6; - + @Deprecated + public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR; + /** - * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMinor}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead. */ - public static final int MOTION_RANGE_TOOL_MINOR = 7; - + @Deprecated + public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR; + /** - * Constant for retrieving the range of values for - * {@link MotionEvent.PointerCoords#orientation}. + * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}. * * @see #getMotionRange + * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead. */ - public static final int MOTION_RANGE_ORIENTATION = 8; - - private static final int MOTION_RANGE_LAST = MOTION_RANGE_ORIENTATION; + @Deprecated + public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION; /** * There is no keyboard. @@ -261,10 +277,9 @@ public final class InputDevice implements Parcelable { * The keyboard supports a complement of alphabetic keys. */ public static final int KEYBOARD_TYPE_ALPHABETIC = 2; - + // Called by native code. private InputDevice() { - mMotionRanges = new MotionRange[MOTION_RANGE_LAST + 1]; } /** @@ -335,72 +350,69 @@ public final class InputDevice implements Parcelable { public KeyCharacterMap getKeyCharacterMap() { return KeyCharacterMap.load(mId); } - + /** - * Gets information about the range of values for a particular {@link MotionEvent} - * coordinate. - * @param rangeType The motion range constant. - * @return The range of values, or null if the requested coordinate is not + * Gets information about the range of values for a particular {@link MotionEvent} axis. + * @param axis The axis constant. + * @return The range of values, or null if the requested axis is not * supported by the device. + * + * @see MotionEvent#AXIS_X + * @see MotionEvent#AXIS_Y */ - public MotionRange getMotionRange(int rangeType) { - if (rangeType < 0 || rangeType > MOTION_RANGE_LAST) { - throw new IllegalArgumentException("Requested range is out of bounds."); - } - - return mMotionRanges[rangeType]; + public MotionRange getMotionRange(int axis) { + return mMotionRanges.get(axis); } - - private void addMotionRange(int rangeType, float min, float max, float flat, float fuzz) { - if (rangeType >= 0 && rangeType <= MOTION_RANGE_LAST) { - MotionRange range = new MotionRange(min, max, flat, fuzz); - mMotionRanges[rangeType] = range; - } + + // Called by native code. + private void addMotionRange(int axis, float min, float max, float flat, float fuzz) { + mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz)); } - + /** - * Provides information about the range of values for a particular {@link MotionEvent} - * coordinate. + * Provides information about the range of values for a particular {@link MotionEvent} axis. + * + * @see InputDevice#getMotionRange(int) */ public static final class MotionRange { private float mMin; private float mMax; private float mFlat; private float mFuzz; - + private MotionRange(float min, float max, float flat, float fuzz) { mMin = min; mMax = max; mFlat = flat; mFuzz = fuzz; } - + /** - * Gets the minimum value for the coordinate. - * @return The minimum value. + * Gets the minimum value for the axis. + * @return The (inclusive) minimum value. */ public float getMin() { return mMin; } - + /** - * Gets the maximum value for the coordinate. - * @return The minimum value. + * Gets the maximum value for the axis. + * @return The (inclusive) maximum value. */ public float getMax() { return mMax; } - + /** - * Gets the range of the coordinate (difference between maximum and minimum). + * Gets the range of the axis (difference between maximum and minimum plus one). * @return The range of values. */ public float getRange() { - return mMax - mMin; + return mMax - mMin + 1; } - + /** - * Gets the extent of the center flat position with respect to this coordinate. + * Gets the extent of the center flat position with respect to this axis. * For example, a flat value of 8 means that the center position is between -8 and +8. * This value is mainly useful for calibrating self-centering devices. * @return The extent of the center flat position. @@ -408,9 +420,9 @@ public final class InputDevice implements Parcelable { public float getFlat() { return mFlat; } - + /** - * Gets the error tolerance for input device measurements with respect to this coordinate. + * Gets the error tolerance for input device measurements with respect to this axis. * For example, a value of 2 indicates that the measured value may be up to +/- 2 units * away from the actual value due to noise and device sensitivity limitations. * @return The error tolerance. @@ -419,7 +431,7 @@ public final class InputDevice implements Parcelable { return mFuzz; } } - + public static final Parcelable.Creator<InputDevice> CREATOR = new Parcelable.Creator<InputDevice>() { public InputDevice createFromParcel(Parcel in) { @@ -438,15 +450,13 @@ public final class InputDevice implements Parcelable { mName = in.readString(); mSources = in.readInt(); mKeyboardType = in.readInt(); - + for (;;) { - int rangeType = in.readInt(); - if (rangeType < 0) { + int axis = in.readInt(); + if (axis < 0) { break; } - - addMotionRange(rangeType, - in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); + addMotionRange(axis, in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); } } @@ -456,25 +466,25 @@ public final class InputDevice implements Parcelable { out.writeString(mName); out.writeInt(mSources); out.writeInt(mKeyboardType); - - for (int i = 0; i <= MOTION_RANGE_LAST; i++) { - MotionRange range = mMotionRanges[i]; - if (range != null) { - out.writeInt(i); - out.writeFloat(range.mMin); - out.writeFloat(range.mMax); - out.writeFloat(range.mFlat); - out.writeFloat(range.mFuzz); - } + + final int numAxes = mMotionRanges.size(); + for (int i = 0; i < numAxes; i++) { + int axis = mMotionRanges.keyAt(i); + MotionRange range = mMotionRanges.valueAt(i); + out.writeInt(axis); + out.writeFloat(range.mMin); + out.writeFloat(range.mMax); + out.writeFloat(range.mFlat); + out.writeFloat(range.mFuzz); } out.writeInt(-1); } - + @Override public int describeContents() { return 0; } - + @Override public String toString() { StringBuilder description = new StringBuilder(); @@ -493,29 +503,32 @@ public final class InputDevice implements Parcelable { break; } description.append("\n"); - - description.append(" Sources:"); + + description.append(" Sources: ").append(Integer.toHexString(mSources)).append(" ("); appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse"); appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball"); appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); - description.append("\n"); - - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_X, "x"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_Y, "y"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_PRESSURE, "pressure"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_SIZE, "size"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MAJOR, "touchMajor"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MINOR, "touchMinor"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MAJOR, "toolMajor"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MINOR, "toolMinor"); - appendRangeDescriptionIfApplicable(description, MOTION_RANGE_ORIENTATION, "orientation"); - + appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick"); + appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); + description.append(" )\n"); + + final int numAxes = mMotionRanges.size(); + for (int i = 0; i < numAxes; i++) { + int axis = mMotionRanges.keyAt(i); + MotionRange range = mMotionRanges.valueAt(i); + description.append(" ").append(MotionEvent.axisToString(axis)); + description.append(": min=").append(range.mMin); + description.append(" max=").append(range.mMax); + description.append(" flat=").append(range.mFlat); + description.append(" fuzz=").append(range.mFuzz); + description.append("\n"); + } return description.toString(); } - + private void appendSourceDescriptionIfApplicable(StringBuilder description, int source, String sourceName) { if ((mSources & source) == source) { @@ -523,17 +536,4 @@ public final class InputDevice implements Parcelable { description.append(sourceName); } } - - private void appendRangeDescriptionIfApplicable(StringBuilder description, - int rangeType, String rangeName) { - MotionRange range = mMotionRanges[rangeType]; - if (range != null) { - description.append(" Range[").append(rangeName); - description.append("]: min=").append(range.mMin); - description.append(" max=").append(range.mMax); - description.append(" flat=").append(range.mFlat); - description.append(" fuzz=").append(range.mFuzz); - description.append("\n"); - } - } } diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java index 184e0fc..f6aeb39 100755 --- a/core/java/android/view/InputEvent.java +++ b/core/java/android/view/InputEvent.java @@ -24,11 +24,6 @@ import android.os.Parcelable; */ public abstract class InputEvent implements Parcelable { /** @hide */ - protected int mDeviceId; - /** @hide */ - protected int mSource; - - /** @hide */ protected static final int PARCEL_TOKEN_MOTION_EVENT = 1; /** @hide */ protected static final int PARCEL_TOKEN_KEY_EVENT = 2; @@ -45,55 +40,37 @@ public abstract class InputEvent implements Parcelable { * @return The device id. * @see InputDevice#getDevice */ - public final int getDeviceId() { - return mDeviceId; - } - + public abstract int getDeviceId(); + /** * Gets the device that this event came from. * * @return The device, or null if unknown. */ public final InputDevice getDevice() { - return InputDevice.getDevice(mDeviceId); + return InputDevice.getDevice(getDeviceId()); } - + /** * Gets the source of the event. * * @return The event source or {@link InputDevice#SOURCE_UNKNOWN} if unknown. * @see InputDevice#getSourceInfo */ - public final int getSource() { - return mSource; - } - + public abstract int getSource(); + /** * Modifies the source of the event. - * @param source The source. - * + * + * @param source The new source. * @hide */ - public final void setSource(int source) { - mSource = source; - } - + public abstract void setSource(int source); + public int describeContents() { return 0; } - - /** @hide */ - protected final void readBaseFromParcel(Parcel in) { - mDeviceId = in.readInt(); - mSource = in.readInt(); - } - - /** @hide */ - protected final void writeBaseToParcel(Parcel out) { - out.writeInt(mDeviceId); - out.writeInt(mSource); - } - + public static final Parcelable.Creator<InputEvent> CREATOR = new Parcelable.Creator<InputEvent>() { public InputEvent createFromParcel(Parcel in) { diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 766969a..3f6a04b 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1180,6 +1180,8 @@ public class KeyEvent extends InputEvent implements Parcelable { private KeyEvent mNext; private boolean mRecycled; + private int mDeviceId; + private int mSource; private int mMetaState; private int mAction; private int mKeyCode; @@ -1651,6 +1653,23 @@ public class KeyEvent extends InputEvent implements Parcelable { return native_hasDefaultAction(mKeyCode); } + /** {@inheritDoc} */ + @Override + public final int getDeviceId() { + return mDeviceId; + } + + /** {@inheritDoc} */ + @Override + public final int getSource() { + return mSource; + } + + /** {@inheritDoc} */ + @Override + public final void setSource(int source) { + mSource = source; + } /** * <p>Returns the state of the meta keys.</p> @@ -2651,8 +2670,8 @@ public class KeyEvent extends InputEvent implements Parcelable { } private KeyEvent(Parcel in) { - readBaseFromParcel(in); - + mDeviceId = in.readInt(); + mSource = in.readInt(); mAction = in.readInt(); mKeyCode = in.readInt(); mRepeatCount = in.readInt(); @@ -2665,9 +2684,9 @@ public class KeyEvent extends InputEvent implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_KEY_EVENT); - - writeBaseToParcel(out); - + + out.writeInt(mDeviceId); + out.writeInt(mSource); out.writeInt(mAction); out.writeInt(mKeyCode); out.writeInt(mRepeatCount); diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 5db4895..6673be2 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -102,7 +102,7 @@ import android.os.SystemClock; * </p> */ public final class MotionEvent extends InputEvent implements Parcelable { - private static final long MS_PER_NS = 1000000; + private static final long NS_PER_MS = 1000000; private static final boolean TRACK_RECYCLED_LOCATION = false; /** @@ -261,123 +261,241 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int EDGE_RIGHT = 0x00000008; - /* - * Offset for the sample's X coordinate. - */ - static private final int SAMPLE_X = 0; - - /* - * Offset for the sample's Y coordinate. - */ - static private final int SAMPLE_Y = 1; - - /* - * Offset for the sample's pressure. - */ - static private final int SAMPLE_PRESSURE = 2; - - /* - * Offset for the sample's size + /** + * Constant used to identify the X axis of a motion event. + * + * The interpretation of the X axis varies by input source. + * It may represent the X position of the center of the touch contact area, + * a relative horizontal displacement of a trackball or joystick, or something else. + * + * @see #getX(int) + * @see #getHistoricalX(int, int) + * @see MotionEvent.PointerCoords#x + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_SIZE = 3; - - /* - * Offset for the sample's touch major axis length. + public static final int AXIS_X = 0; + + /** + * Constant used to identify the Y axis of a motion event. + * + * The interpretation of the Y axis varies by input source. + * It may represent the Y position of the center of the touch contact area, + * a relative vertical displacement of a trackball or joystick, or something else. + * + * @see #getY(int) + * @see #getHistoricalY(int, int) + * @see MotionEvent.PointerCoords#y + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_TOUCH_MAJOR = 4; + public static final int AXIS_Y = 1; - /* - * Offset for the sample's touch minor axis length. + /** + * Constant used to identify the Pressure axis of a motion event. + * + * The pressure axis specifies a normalized value that describes the approximate + * pressure applied to the device by a finger or other tool. + * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), + * although values higher than 1 may be generated depending on the calibration of + * the input device. + * + * @see #getPressure(int) + * @see #getHistoricalPressure(int, int) + * @see MotionEvent.PointerCoords#pressure + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_TOUCH_MINOR = 5; - - /* - * Offset for the sample's tool major axis length. + public static final int AXIS_PRESSURE = 2; + + /** + * Constant used to identify the Size axis of a motion event. + * + * The size axis specifies a normalized value that describes the approximate size + * of the pointer touch area in relation to the maximum detectable size for the device. + * It represents some approximation of the area of the screen being + * pressed; the actual value in pixels corresponding to the + * touch is normalized with the device specific range of values + * and scaled to a value between 0 and 1. The value of size can be used to + * determine fat touch events. + * + * To obtain calibrated size information in terms of pixels, use + * {@link #AXIS_TOUCH_MAJOR} or {@link #AXIS_TOOL_MAJOR} instead. + * + * @see #getSize(int) + * @see #getHistoricalSize(int, int) + * @see MotionEvent.PointerCoords#size + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_TOOL_MAJOR = 6; + public static final int AXIS_SIZE = 3; - /* - * Offset for the sample's tool minor axis length. + /** + * Constant used to identify the TouchMajor axis of a motion event. + * + * The touch major axis specifies the length of the major axis of an ellipse that + * describes the touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see #getTouchMajor(int) + * @see #getHistoricalTouchMajor(int, int) + * @see MotionEvent.PointerCoords#touchMajor + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_TOOL_MINOR = 7; - - /* - * Offset for the sample's orientation. + public static final int AXIS_TOUCH_MAJOR = 4; + + /** + * Constant used to identify the TouchMinor axis of a motion event. + * + * The touch major axis specifies the length of the minor axis of an ellipse that + * describes the touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see #getTouchMinor(int) + * @see #getHistoricalTouchMinor(int, int) + * @see MotionEvent.PointerCoords#touchMinor + * @see InputDevice#getMotionRange */ - static private final int SAMPLE_ORIENTATION = 8; + public static final int AXIS_TOUCH_MINOR = 5; - /* - * Number of data items for each sample. + /** + * Constant used to identify the ToolMajor axis of a motion event. + * + * The tool major axis specifies the length of the major axis of an ellipse that + * describes the size of the approaching tool. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see #getToolMajor(int) + * @see #getHistoricalToolMajor(int, int) + * @see MotionEvent.PointerCoords#toolMajor + * @see InputDevice#getMotionRange */ - static private final int NUM_SAMPLE_DATA = 9; - - /* - * Minimum number of pointers for which to reserve space when allocating new - * motion events. This is explicitly not a bound on the maximum number of pointers. + public static final int AXIS_TOOL_MAJOR = 6; + + /** + * Constant used to identify the ToolMinor axis of a motion event. + * + * The tool minor axis specifies the length of the major axis of an ellipse that + * describes the size of the approaching tool. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see #getToolMinor(int) + * @see #getHistoricalToolMinor(int, int) + * @see MotionEvent.PointerCoords#toolMinor + * @see InputDevice#getMotionRange */ - static private final int BASE_AVAIL_POINTERS = 5; - - /* - * Minimum number of samples for which to reserve space when allocating new motion events. + public static final int AXIS_TOOL_MINOR = 7; + + /** + * Constant used to identify the Orientation axis of a motion event. + * + * The orientation axis specifies the orientation of the touch area and tool area in + * radians clockwise from vertical relative to the vertical plane of the device. + * An angle of 0 degrees indicates that the major axis of contact is oriented + * upwards, is perfectly circular or is of unknown orientation. A positive angle + * indicates that the major axis of contact is oriented to the right. A negative angle + * indicates that the major axis of contact is oriented to the left. + * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians + * (finger pointing fully right). + * + * @see #getOrientation(int) + * @see #getHistoricalOrientation(int, int) + * @see MotionEvent.PointerCoords#orientation + * @see InputDevice#getMotionRange */ - static private final int BASE_AVAIL_SAMPLES = 8; - + public static final int AXIS_ORIENTATION = 8; + + // Private value for history pos that obtains the current sample. + private static final int HISTORY_CURRENT = -0x80000000; + private static final int MAX_RECYCLED = 10; private static final Object gRecyclerLock = new Object(); private static int gRecyclerUsed; private static MotionEvent gRecyclerTop; - private long mDownTimeNano; - private int mAction; - private float mXOffset; - private float mYOffset; - private float mXPrecision; - private float mYPrecision; - private int mEdgeFlags; - private int mMetaState; - private int mFlags; - - 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 event time stamps in nanoseconds. - // Samples are ordered from oldest to newest. - private long[] mEventTimeNanoSamples; + // Shared temporary objects used when translating coordinates supplied by + // the caller into single element PointerCoords and pointer id arrays. + // Must lock gTmpPointerCoords prior to use. + private static final PointerCoords[] gTmpPointerCoords = + new PointerCoords[] { new PointerCoords() }; + private static final int[] gTmpPointerIds = new int[] { 0 /*always 0*/ }; + + // Pointer to the native MotionEvent object that contains the actual data. + private int mNativePtr; private MotionEvent mNext; private RuntimeException mRecycledLocation; private boolean mRecycled; - private native void nativeTransform(Matrix matrix); + private static native int nativeInitialize(int nativePtr, + int deviceId, int source, int action, int flags, int edgeFlags, int metaState, + float xOffset, float yOffset, float xPrecision, float yPrecision, + long downTimeNanos, long eventTimeNanos, + int pointerCount, int[] pointerIds, PointerCoords[] pointerCoords); + private static native int nativeCopy(int destNativePtr, int sourceNativePtr, + boolean keepHistory); + private static native void nativeDispose(int nativePtr); + private static native void nativeAddBatch(int nativePtr, long eventTimeNanos, + PointerCoords[] pointerCoords, int metaState); + + private static native int nativeGetDeviceId(int nativePtr); + private static native int nativeGetSource(int nativePtr); + private static native int nativeSetSource(int nativePtr, int source); + private static native int nativeGetAction(int nativePtr); + private static native void nativeSetAction(int nativePtr, int action); + private static native int nativeGetFlags(int nativePtr); + private static native int nativeGetEdgeFlags(int nativePtr); + private static native void nativeSetEdgeFlags(int nativePtr, int action); + private static native int nativeGetMetaState(int nativePtr); + private static native void nativeOffsetLocation(int nativePtr, float deltaX, float deltaY); + private static native float nativeGetXPrecision(int nativePtr); + private static native float nativeGetYPrecision(int nativePtr); + private static native long nativeGetDownTimeNanos(int nativePtr); + + private static native int nativeGetPointerCount(int nativePtr); + private static native int nativeGetPointerId(int nativePtr, int pointerIndex); + private static native int nativeFindPointerIndex(int nativePtr, int pointerId); + + private static native int nativeGetHistorySize(int nativePtr); + private static native long nativeGetEventTimeNanos(int nativePtr, int historyPos); + private static native float nativeGetRawAxisValue(int nativePtr, + int axis, int pointerIndex, int historyPos); + private static native float nativeGetAxisValue(int nativePtr, + int axis, int pointerIndex, int historyPos); + private static native void nativeGetPointerCoords(int nativePtr, + int pointerIndex, int historyPos, PointerCoords outPointerCoords); + + private static native void nativeScale(int nativePtr, float scale); + private static native void nativeTransform(int nativePtr, Matrix matrix); + + private static native int nativeReadFromParcel(int nativePtr, Parcel parcel); + private static native void nativeWriteToParcel(int nativePtr, Parcel parcel); + + private MotionEvent() { + } - private MotionEvent(int pointerCount, int sampleCount) { - mPointerIdentifiers = new int[pointerCount]; - mDataSamples = new float[pointerCount * sampleCount * NUM_SAMPLE_DATA]; - mEventTimeNanoSamples = new long[sampleCount]; + @Override + protected void finalize() throws Throwable { + try { + if (mNativePtr != 0) { + nativeDispose(mNativePtr); + mNativePtr = 0; + } + } finally { + super.finalize(); + } } - static private MotionEvent obtain(int pointerCount, int sampleCount) { + static private MotionEvent obtain() { final MotionEvent ev; synchronized (gRecyclerLock) { ev = gRecyclerTop; if (ev == null) { - if (pointerCount < BASE_AVAIL_POINTERS) { - pointerCount = BASE_AVAIL_POINTERS; - } - if (sampleCount < BASE_AVAIL_SAMPLES) { - sampleCount = BASE_AVAIL_SAMPLES; - } - return new MotionEvent(pointerCount, sampleCount); + return new MotionEvent(); } gRecyclerTop = ev.mNext; gRecyclerUsed -= 1; @@ -385,23 +503,9 @@ public final class MotionEvent extends InputEvent implements Parcelable { ev.mRecycledLocation = null; ev.mRecycled = false; ev.mNext = null; - - if (ev.mPointerIdentifiers.length < pointerCount) { - ev.mPointerIdentifiers = new int[pointerCount]; - } - - if (ev.mEventTimeNanoSamples.length < sampleCount) { - ev.mEventTimeNanoSamples = new long[sampleCount]; - } - - final int neededDataSamplesLength = pointerCount * sampleCount * NUM_SAMPLE_DATA; - 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. @@ -434,34 +538,15 @@ public final class MotionEvent extends InputEvent implements Parcelable { int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords, int metaState, float xPrecision, float yPrecision, int deviceId, int edgeFlags, int source, int flags) { - MotionEvent ev = obtain(pointers, 1); - ev.mDeviceId = deviceId; - ev.mSource = source; - ev.mEdgeFlags = edgeFlags; - ev.mDownTimeNano = downTime * MS_PER_NS; - ev.mAction = action; - ev.mFlags = flags; - ev.mMetaState = metaState; - ev.mXOffset = 0; - ev.mYOffset = 0; - ev.mXPrecision = xPrecision; - ev.mYPrecision = yPrecision; - - ev.mNumPointers = pointers; - ev.mNumSamples = 1; - - ev.mLastDataSampleIndex = 0; - ev.mLastEventTimeNanoSampleIndex = 0; - - System.arraycopy(pointerIds, 0, ev.mPointerIdentifiers, 0, pointers); - - ev.mEventTimeNanoSamples[0] = eventTime * MS_PER_NS; - - ev.setPointerCoordsAtSampleIndex(0, pointerCoords); - + MotionEvent ev = obtain(); + ev.mNativePtr = nativeInitialize(ev.mNativePtr, + deviceId, source, action, flags, edgeFlags, metaState, + 0, 0, xPrecision, yPrecision, + downTime * NS_PER_MS, eventTime * NS_PER_MS, + pointers, pointerIds, pointerCoords); return ev; } - + /** * Create a new MotionEvent, filling in all of the basic values that * define the motion. @@ -496,31 +581,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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(1, 1); - ev.mDeviceId = deviceId; - ev.mSource = InputDevice.SOURCE_UNKNOWN; - ev.mEdgeFlags = edgeFlags; - ev.mDownTimeNano = downTime * MS_PER_NS; - ev.mAction = action; - ev.mFlags = 0; - ev.mMetaState = metaState; - ev.mXOffset = 0; - ev.mYOffset = 0; - ev.mXPrecision = xPrecision; - ev.mYPrecision = yPrecision; - - ev.mNumPointers = 1; - ev.mNumSamples = 1; - - ev.mLastDataSampleIndex = 0; - ev.mLastEventTimeNanoSampleIndex = 0; - - ev.mPointerIdentifiers[0] = 0; - - ev.mEventTimeNanoSamples[0] = eventTime * MS_PER_NS; - - ev.setPointerCoordsAtSampleIndex(0, x, y, pressure, size); - return ev; + synchronized (gTmpPointerCoords) { + final PointerCoords pc = gTmpPointerCoords[0]; + pc.clear(); + pc.x = x; + pc.y = y; + pc.pressure = pressure; + pc.size = size; + + MotionEvent ev = obtain(); + ev.mNativePtr = nativeInitialize(ev.mNativePtr, + deviceId, InputDevice.SOURCE_UNKNOWN, action, 0, edgeFlags, metaState, + 0, 0, xPrecision, yPrecision, + downTime * NS_PER_MS, eventTime * NS_PER_MS, + 1, gTmpPointerIds, gTmpPointerCoords); + return ev; + } } /** @@ -592,31 +668,13 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** * Create a new MotionEvent, copying from an existing one. */ - static public MotionEvent obtain(MotionEvent o) { - MotionEvent ev = obtain(o.mNumPointers, o.mNumSamples); - ev.mDeviceId = o.mDeviceId; - ev.mSource = o.mSource; - ev.mEdgeFlags = o.mEdgeFlags; - ev.mDownTimeNano = o.mDownTimeNano; - ev.mAction = o.mAction; - ev.mFlags = o.mFlags; - 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; - - ev.mLastDataSampleIndex = o.mLastDataSampleIndex; - ev.mLastEventTimeNanoSampleIndex = o.mLastEventTimeNanoSampleIndex; - - System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, numPointers); - - System.arraycopy(o.mEventTimeNanoSamples, 0, ev.mEventTimeNanoSamples, 0, numSamples); - - System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, - numPointers * numSamples * NUM_SAMPLE_DATA); + static public MotionEvent obtain(MotionEvent other) { + if (other == null) { + throw new IllegalArgumentException("other motion event must not be null"); + } + + MotionEvent ev = obtain(); + ev.mNativePtr = nativeCopy(ev.mNativePtr, other.mNativePtr, true /*keepHistory*/); return ev; } @@ -624,32 +682,13 @@ public final class MotionEvent extends InputEvent implements Parcelable { * Create a new MotionEvent, copying from an existing one, but not including * any historical point information. */ - static public MotionEvent obtainNoHistory(MotionEvent o) { - MotionEvent ev = obtain(o.mNumPointers, 1); - ev.mDeviceId = o.mDeviceId; - ev.mSource = o.mSource; - ev.mEdgeFlags = o.mEdgeFlags; - ev.mDownTimeNano = o.mDownTimeNano; - ev.mAction = o.mAction; - o.mFlags = o.mFlags; - 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.mLastDataSampleIndex = 0; - ev.mLastEventTimeNanoSampleIndex = 0; - - 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); + static public MotionEvent obtainNoHistory(MotionEvent other) { + if (other == null) { + throw new IllegalArgumentException("other motion event must not be null"); + } + + MotionEvent ev = obtain(); + ev.mNativePtr = nativeCopy(ev.mNativePtr, other.mNativePtr, false /*keepHistory*/); return ev; } @@ -675,7 +714,6 @@ public final class MotionEvent extends InputEvent implements Parcelable { synchronized (gRecyclerLock) { if (gRecyclerUsed < MAX_RECYCLED) { gRecyclerUsed++; - mNumSamples = 0; mNext = gRecyclerTop; gRecyclerTop = this; } @@ -688,23 +726,25 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @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? - history[i + SAMPLE_TOUCH_MAJOR] *= scale; - history[i + SAMPLE_TOUCH_MINOR] *= scale; - history[i + SAMPLE_TOOL_MAJOR] *= scale; - history[i + SAMPLE_TOOL_MINOR] *= scale; - } + nativeScale(mNativePtr, scale); + } + + /** {@inheritDoc} */ + @Override + public final int getDeviceId() { + return nativeGetDeviceId(mNativePtr); + } + + /** {@inheritDoc} */ + @Override + public final int getSource() { + return nativeGetSource(mNativePtr); + } + + /** {@inheritDoc} */ + @Override + public final void setSource(int source) { + nativeSetSource(mNativePtr, source); } /** @@ -715,7 +755,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * and pointer index. */ public final int getAction() { - return mAction; + return nativeGetAction(mNativePtr); } /** @@ -727,7 +767,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * pointer actions. */ public final int getActionMasked() { - return mAction & ACTION_MASK; + return nativeGetAction(mNativePtr) & ACTION_MASK; } /** @@ -739,7 +779,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { * gone down or up. */ public final int getActionIndex() { - return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT; + return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK) + >> ACTION_POINTER_INDEX_SHIFT; } /** @@ -748,7 +789,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #FLAG_WINDOW_IS_OBSCURED */ public final int getFlags() { - return mFlags; + return nativeGetFlags(mNativePtr); } /** @@ -756,14 +797,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { * a stream of position events. */ public final long getDownTime() { - return mDownTimeNano / MS_PER_NS; + return nativeGetDownTimeNanos(mNativePtr) / NS_PER_MS; } /** * Returns the time (in ms) when this specific event was generated. */ public final long getEventTime() { - return mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] / MS_PER_NS; + return nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT) / NS_PER_MS; } /** @@ -773,79 +814,110 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @hide */ public final long getEventTimeNano() { - return mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex]; + return nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT); } /** * {@link #getX(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_X */ public final float getX() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_X] + mXOffset; + return nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT); } /** * {@link #getY(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_Y */ public final float getY() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_Y] + mYOffset; + return nativeGetAxisValue(mNativePtr, AXIS_Y, 0, HISTORY_CURRENT); } /** * {@link #getPressure(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_PRESSURE */ public final float getPressure() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_PRESSURE]; + return nativeGetAxisValue(mNativePtr, AXIS_PRESSURE, 0, HISTORY_CURRENT); } /** * {@link #getSize(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_SIZE */ public final float getSize() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_SIZE]; + return nativeGetAxisValue(mNativePtr, AXIS_SIZE, 0, HISTORY_CURRENT); } /** * {@link #getTouchMajor(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_TOUCH_MAJOR */ public final float getTouchMajor() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_TOUCH_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MAJOR, 0, HISTORY_CURRENT); } /** * {@link #getTouchMinor(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_TOUCH_MINOR */ public final float getTouchMinor() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_TOUCH_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MINOR, 0, HISTORY_CURRENT); } /** * {@link #getToolMajor(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_TOOL_MAJOR */ public final float getToolMajor() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_TOOL_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MAJOR, 0, HISTORY_CURRENT); } /** * {@link #getToolMinor(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_TOOL_MINOR */ public final float getToolMinor() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_TOOL_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MINOR, 0, HISTORY_CURRENT); } - + /** * {@link #getOrientation(int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @see #AXIS_ORIENTATION */ public final float getOrientation() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_ORIENTATION]; + return nativeGetAxisValue(mNativePtr, AXIS_ORIENTATION, 0, HISTORY_CURRENT); + } + + /** + * {@link #getAxisValue(int)} for the first pointer index (may be an + * arbitrary pointer identifier). + * + * @param axis The axis identifier for the axis value to retrieve. + * + * @see #AXIS_X + * @see #AXIS_Y + */ + public final float getAxisValue(int axis) { + return nativeGetAxisValue(mNativePtr, axis, 0, HISTORY_CURRENT); } /** @@ -853,7 +925,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * >= 1. */ public final int getPointerCount() { - return mNumPointers; + return nativeGetPointerCount(mNativePtr); } /** @@ -865,7 +937,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * (the first pointer that is down) to {@link #getPointerCount()}-1. */ public final int getPointerId(int pointerIndex) { - return mPointerIdentifiers[pointerIndex]; + return nativeGetPointerId(mNativePtr, pointerIndex); } /** @@ -877,14 +949,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * that pointer identifier. */ public final int findPointerIndex(int pointerId) { - int i = mNumPointers; - while (i > 0) { - i--; - if (mPointerIdentifiers[i] == pointerId) { - return i; - } - } - return -1; + return nativeFindPointerIndex(mNativePtr, pointerId); } /** @@ -895,10 +960,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * value may have a fraction for input devices that are sub-pixel precise. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_X */ public final float getX(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset; + return nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, HISTORY_CURRENT); } /** @@ -909,10 +975,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * value may have a fraction for input devices that are sub-pixel precise. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_Y */ public final float getY(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset; + return nativeGetAxisValue(mNativePtr, AXIS_Y, pointerIndex, HISTORY_CURRENT); } /** @@ -925,10 +992,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * the input device. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_PRESSURE */ public final float getPressure(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_PRESSURE]; + return nativeGetAxisValue(mNativePtr, AXIS_PRESSURE, pointerIndex, HISTORY_CURRENT); } /** @@ -942,10 +1010,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * determine fat touch events. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_SIZE */ public final float getSize(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_SIZE]; + return nativeGetAxisValue(mNativePtr, AXIS_SIZE, pointerIndex, HISTORY_CURRENT); } /** @@ -955,10 +1024,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * identifier for this index). * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_TOUCH_MAJOR */ public final float getTouchMajor(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MAJOR, pointerIndex, HISTORY_CURRENT); } /** @@ -968,10 +1038,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * identifier for this index). * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_TOUCH_MINOR */ public final float getTouchMinor(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MINOR, pointerIndex, HISTORY_CURRENT); } /** @@ -983,10 +1054,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * touching the device independent of its actual touch area at the point of contact. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_TOOL_MAJOR */ public final float getToolMajor(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MAJOR, pointerIndex, HISTORY_CURRENT); } /** @@ -998,10 +1070,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * touching the device independent of its actual touch area at the point of contact. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_TOOL_MINOR */ public final float getToolMinor(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MINOR, pointerIndex, HISTORY_CURRENT); } /** @@ -1016,12 +1089,29 @@ public final class MotionEvent extends InputEvent implements Parcelable { * (finger pointing fully right). * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. + * + * @see #AXIS_ORIENTATION */ public final float getOrientation(int pointerIndex) { - return mDataSamples[mLastDataSampleIndex - + pointerIndex * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION]; + return nativeGetAxisValue(mNativePtr, AXIS_ORIENTATION, pointerIndex, HISTORY_CURRENT); } - + + /** + * Returns the value of the requested axis for the given pointer <em>index</em> + * (use {@link #getPointerId(int)} to find the pointer identifier for this index). + * + * @param axis The axis identifier for the axis value to retrieve. + * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 + * (the first pointer that is down) to {@link #getPointerCount()}-1. + * @return The value of the axis, or 0 if the axis is not available. + * + * @see #AXIS_X + * @see #AXIS_Y + */ + public final float getAxisValue(int axis, int pointerIndex) { + return nativeGetAxisValue(mNativePtr, axis, pointerIndex, HISTORY_CURRENT); + } + /** * Populates a {@link PointerCoords} object with pointer coordinate data for * the specified pointer index. @@ -1029,10 +1119,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. * @param outPointerCoords The pointer coordinate object to populate. + * + * @see PointerCoords */ public final void getPointerCoords(int pointerIndex, PointerCoords outPointerCoords) { - final int sampleIndex = mLastDataSampleIndex + pointerIndex * NUM_SAMPLE_DATA; - getPointerCoordsAtSampleIndex(sampleIndex, outPointerCoords); + nativeGetPointerCoords(mNativePtr, pointerIndex, HISTORY_CURRENT, outPointerCoords); } /** @@ -1046,7 +1137,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see KeyEvent#getMetaState() */ public final int getMetaState() { - return mMetaState; + return nativeGetMetaState(mNativePtr); } /** @@ -1054,39 +1145,49 @@ public final class MotionEvent extends InputEvent implements Parcelable { * 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. + * + * @see getX() + * @see #AXIS_X */ public final float getRawX() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_X]; + return nativeGetRawAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT); } - + /** * Returns the original raw Y 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. + * + * @see getY() + * @see #AXIS_Y */ public final float getRawY() { - return mDataSamples[mLastDataSampleIndex + SAMPLE_Y]; + return nativeGetRawAxisValue(mNativePtr, AXIS_Y, 0, HISTORY_CURRENT); } /** * Return the precision of the X coordinates being reported. You can - * multiple this number with {@link #getX} to find the actual hardware + * multiply this number with {@link #getX} to find the actual hardware * value of the X coordinate. * @return Returns the precision of X coordinates being reported. + * + * @see #AXIS_X */ public final float getXPrecision() { - return mXPrecision; + return nativeGetXPrecision(mNativePtr); } /** * Return the precision of the Y coordinates being reported. You can - * multiple this number with {@link #getY} to find the actual hardware + * multiply this number with {@link #getY} to find the actual hardware * value of the Y coordinate. * @return Returns the precision of Y coordinates being reported. + * + * @see #AXIS_Y */ public final float getYPrecision() { - return mYPrecision; + return nativeGetYPrecision(mNativePtr); } /** @@ -1098,7 +1199,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @return Returns the number of historical points in the event. */ public final int getHistorySize() { - return mLastEventTimeNanoSampleIndex; + return nativeGetHistorySize(mNativePtr); } /** @@ -1112,81 +1213,161 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #getEventTime */ public final long getHistoricalEventTime(int pos) { - return mEventTimeNanoSamples[pos] / MS_PER_NS; + return nativeGetEventTimeNanos(mNativePtr, pos) / NS_PER_MS; } /** - * {@link #getHistoricalX(int)} for the first pointer index (may be an + * {@link #getHistoricalX(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getX() + * @see #AXIS_X */ public final float getHistoricalX(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset; + return nativeGetAxisValue(mNativePtr, AXIS_X, 0, pos); } /** - * {@link #getHistoricalY(int)} for the first pointer index (may be an + * {@link #getHistoricalY(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getY() + * @see #AXIS_Y */ public final float getHistoricalY(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset; + return nativeGetAxisValue(mNativePtr, AXIS_Y, 0, pos); } /** - * {@link #getHistoricalPressure(int)} for the first pointer index (may be an + * {@link #getHistoricalPressure(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getPressure() + * @see #AXIS_PRESSURE */ public final float getHistoricalPressure(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_PRESSURE]; + return nativeGetAxisValue(mNativePtr, AXIS_PRESSURE, 0, pos); } /** - * {@link #getHistoricalSize(int)} for the first pointer index (may be an + * {@link #getHistoricalSize(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getSize() + * @see #AXIS_SIZE */ public final float getHistoricalSize(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_SIZE]; + return nativeGetAxisValue(mNativePtr, AXIS_SIZE, 0, pos); } /** - * {@link #getHistoricalTouchMajor(int)} for the first pointer index (may be an + * {@link #getHistoricalTouchMajor(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getTouchMajor() + * @see #AXIS_TOUCH_MAJOR */ public final float getHistoricalTouchMajor(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MAJOR, 0, pos); } /** - * {@link #getHistoricalTouchMinor(int)} for the first pointer index (may be an + * {@link #getHistoricalTouchMinor(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getTouchMinor() + * @see #AXIS_TOUCH_MINOR */ public final float getHistoricalTouchMinor(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MINOR, 0, pos); } /** - * {@link #getHistoricalToolMajor(int)} for the first pointer index (may be an + * {@link #getHistoricalToolMajor(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getToolMajor() + * @see #AXIS_TOOL_MAJOR */ public final float getHistoricalToolMajor(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MAJOR, 0, pos); } /** - * {@link #getHistoricalToolMinor(int)} for the first pointer index (may be an + * {@link #getHistoricalToolMinor(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getToolMinor() + * @see #AXIS_TOOL_MINOR */ public final float getHistoricalToolMinor(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MINOR, 0, pos); } /** - * {@link #getHistoricalOrientation(int)} for the first pointer index (may be an + * {@link #getHistoricalOrientation(int, int)} for the first pointer index (may be an * arbitrary pointer identifier). + * + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getOrientation() + * @see #AXIS_ORIENTATION */ public final float getHistoricalOrientation(int pos) { - return mDataSamples[pos * mNumPointers * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION]; + return nativeGetAxisValue(mNativePtr, AXIS_ORIENTATION, 0, pos); } - + + /** + * {@link #getHistoricalAxisValue(int, int, int)} for the first pointer index (may be an + * arbitrary pointer identifier). + * + * @param axis The axis identifier for the axis value to retrieve. + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * + * @see #getHistorySize + * @see #getAxisValue(int) + * @see #AXIS_X + * @see #AXIS_Y + */ + public final float getHistoricalAxisValue(int axis, int pos) { + return nativeGetAxisValue(mNativePtr, axis, 0, pos); + } + /** * Returns a historical X coordinate, as per {@link #getX(int)}, that * occurred between this event and the previous event for the given pointer. @@ -1198,11 +1379,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getX + * @see #getX(int) + * @see #AXIS_X */ public final float getHistoricalX(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_X] + mXOffset; + return nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, pos); } /** @@ -1216,11 +1397,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getY + * @see #getY(int) + * @see #AXIS_Y */ public final float getHistoricalY(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_Y] + mYOffset; + return nativeGetAxisValue(mNativePtr, AXIS_Y, pointerIndex, pos); } /** @@ -1234,11 +1415,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getPressure + * @see #getPressure(int) + * @see #AXIS_PRESSURE */ public final float getHistoricalPressure(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_PRESSURE]; + return nativeGetAxisValue(mNativePtr, AXIS_PRESSURE, pointerIndex, pos); } /** @@ -1252,11 +1433,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getSize + * @see #getSize(int) + * @see #AXIS_SIZE */ public final float getHistoricalSize(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_SIZE]; + return nativeGetAxisValue(mNativePtr, AXIS_SIZE, pointerIndex, pos); } /** @@ -1270,11 +1451,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getTouchMajor + * @see #getTouchMajor(int) + * @see #AXIS_TOUCH_MAJOR */ public final float getHistoricalTouchMajor(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MAJOR, pointerIndex, pos); } /** @@ -1288,11 +1469,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getTouchMinor + * @see #getTouchMinor(int) + * @see #AXIS_TOUCH_MINOR */ public final float getHistoricalTouchMinor(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_TOUCH_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOUCH_MINOR, pointerIndex, pos); } /** @@ -1306,11 +1487,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getToolMajor + * @see #getToolMajor(int) + * @see #AXIS_TOOL_MAJOR */ public final float getHistoricalToolMajor(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_TOOL_MAJOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MAJOR, pointerIndex, pos); } /** @@ -1324,11 +1505,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getToolMinor + * @see #getToolMinor(int) + * @see #AXIS_TOOL_MINOR */ public final float getHistoricalToolMinor(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_TOOL_MINOR]; + return nativeGetAxisValue(mNativePtr, AXIS_TOOL_MINOR, pointerIndex, pos); } /** @@ -1342,11 +1523,30 @@ public final class MotionEvent extends InputEvent implements Parcelable { * {@link #getHistorySize} * * @see #getHistorySize - * @see #getOrientation + * @see #getOrientation(int) + * @see #AXIS_ORIENTATION */ public final float getHistoricalOrientation(int pointerIndex, int pos) { - return mDataSamples[(pos * mNumPointers + pointerIndex) - * NUM_SAMPLE_DATA + SAMPLE_ORIENTATION]; + return nativeGetAxisValue(mNativePtr, AXIS_ORIENTATION, pointerIndex, pos); + } + + /** + * Returns the historical value of the requested axis, as per {@link #getAxisValue(int, int)}, + * occurred between this event and the previous event for the given pointer. + * Only applies to ACTION_MOVE events. + * + * @param axis The axis identifier for the axis value to retrieve. + * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 + * (the first pointer that is down) to {@link #getPointerCount()}-1. + * @param pos Which historical value to return; must be less than + * {@link #getHistorySize} + * @return The value of the axis, or 0 if the axis is not available. + * + * @see #AXIS_X + * @see #AXIS_Y + */ + public final float getHistoricalAxisValue(int axis, int pointerIndex, int pos) { + return nativeGetAxisValue(mNativePtr, axis, pointerIndex, pos); } /** @@ -1363,11 +1563,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { * * @see #getHistorySize * @see #getPointerCoords + * @see PointerCoords */ public final void getHistoricalPointerCoords(int pointerIndex, int pos, PointerCoords outPointerCoords) { - final int sampleIndex = (pos * mNumPointers + pointerIndex) * NUM_SAMPLE_DATA; - getPointerCoordsAtSampleIndex(sampleIndex, outPointerCoords); + nativeGetPointerCoords(mNativePtr, pointerIndex, pos, outPointerCoords); } /** @@ -1381,10 +1581,9 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #EDGE_BOTTOM */ public final int getEdgeFlags() { - return mEdgeFlags; + return nativeGetEdgeFlags(mNativePtr); } - /** * Sets the bitfield indicating which edges, if any, were touched by this * MotionEvent. @@ -1392,14 +1591,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see #getEdgeFlags() */ public final void setEdgeFlags(int flags) { - mEdgeFlags = flags; + nativeSetEdgeFlags(mNativePtr, flags); } /** * Sets this event's action. */ public final void setAction(int action) { - mAction = action; + nativeSetAction(mNativePtr, action); } /** @@ -1408,8 +1607,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param deltaY Amount to add to the current Y coordinate of the event. */ public final void offsetLocation(float deltaX, float deltaY) { - mXOffset += deltaX; - mYOffset += deltaY; + nativeOffsetLocation(mNativePtr, deltaX, deltaY); } /** @@ -1420,10 +1618,9 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param y New absolute Y location. */ public final void setLocation(float x, float y) { - final float[] dataSamples = mDataSamples; - final int lastDataSampleIndex = mLastDataSampleIndex; - mXOffset = x - dataSamples[lastDataSampleIndex + SAMPLE_X]; - mYOffset = y - dataSamples[lastDataSampleIndex + SAMPLE_Y]; + float oldX = getX(); + float oldY = getY(); + nativeOffsetLocation(mNativePtr, x - oldX, y - oldY); } /** @@ -1436,85 +1633,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { throw new IllegalArgumentException("matrix must not be null"); } - nativeTransform(matrix); - } - - private final void getPointerCoordsAtSampleIndex(int sampleIndex, - PointerCoords outPointerCoords) { - final float[] dataSamples = mDataSamples; - outPointerCoords.x = dataSamples[sampleIndex + SAMPLE_X] + mXOffset; - outPointerCoords.y = dataSamples[sampleIndex + SAMPLE_Y] + mYOffset; - outPointerCoords.pressure = dataSamples[sampleIndex + SAMPLE_PRESSURE]; - outPointerCoords.size = dataSamples[sampleIndex + SAMPLE_SIZE]; - outPointerCoords.touchMajor = dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR]; - outPointerCoords.touchMinor = dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR]; - outPointerCoords.toolMajor = dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR]; - outPointerCoords.toolMinor = dataSamples[sampleIndex + SAMPLE_TOOL_MINOR]; - outPointerCoords.orientation = dataSamples[sampleIndex + SAMPLE_ORIENTATION]; - } - - private final void setPointerCoordsAtSampleIndex(int sampleIndex, - PointerCoords[] pointerCoords) { - final int numPointers = mNumPointers; - for (int i = 0; i < numPointers; i++) { - setPointerCoordsAtSampleIndex(sampleIndex, pointerCoords[i]); - sampleIndex += NUM_SAMPLE_DATA; - } - } - - private final void setPointerCoordsAtSampleIndex(int sampleIndex, - PointerCoords pointerCoords) { - final float[] dataSamples = mDataSamples; - dataSamples[sampleIndex + SAMPLE_X] = pointerCoords.x - mXOffset; - dataSamples[sampleIndex + SAMPLE_Y] = pointerCoords.y - mYOffset; - dataSamples[sampleIndex + SAMPLE_PRESSURE] = pointerCoords.pressure; - dataSamples[sampleIndex + SAMPLE_SIZE] = pointerCoords.size; - dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pointerCoords.touchMajor; - dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pointerCoords.touchMinor; - dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = pointerCoords.toolMajor; - dataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = pointerCoords.toolMinor; - dataSamples[sampleIndex + SAMPLE_ORIENTATION] = pointerCoords.orientation; - } - - private final void setPointerCoordsAtSampleIndex(int sampleIndex, - float x, float y, float pressure, float size) { - final float[] dataSamples = mDataSamples; - dataSamples[sampleIndex + SAMPLE_X] = x - mXOffset; - dataSamples[sampleIndex + SAMPLE_Y] = y - mYOffset; - dataSamples[sampleIndex + SAMPLE_PRESSURE] = pressure; - dataSamples[sampleIndex + SAMPLE_SIZE] = size; - dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pressure; - dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pressure; - dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = size; - dataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = size; - dataSamples[sampleIndex + SAMPLE_ORIENTATION] = 0; - } - - 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; + nativeTransform(mNativePtr, matrix); } /** * Add a new movement to the batch of movements in this event. The event's * current location, position and size is updated to the new values. * The current values in the event are added to a list of historical values. - * + * * Only applies to {@link #ACTION_MOVE} events. * * @param eventTime The time stamp (in ms) for this data. @@ -1526,19 +1652,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public final void addBatch(long eventTime, float x, float y, float pressure, float size, int metaState) { - incrementNumSamplesAndReserveStorage(NUM_SAMPLE_DATA); - - mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS; - setPointerCoordsAtSampleIndex(mLastDataSampleIndex, x, y, pressure, size); - - mMetaState |= metaState; + synchronized (gTmpPointerCoords) { + final PointerCoords pc = gTmpPointerCoords[0]; + pc.clear(); + pc.x = x; + pc.y = y; + pc.pressure = pressure; + pc.size = size; + nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, gTmpPointerCoords, metaState); + } } /** * Add a new movement to the batch of movements in this event. The event's * current location, position and size is updated to the new values. * The current values in the event are added to a list of historical values. - * + * * Only applies to {@link #ACTION_MOVE} events. * * @param eventTime The time stamp (in ms) for this data. @@ -1546,20 +1675,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param metaState Meta key state. */ public final void addBatch(long eventTime, PointerCoords[] pointerCoords, int metaState) { - final int dataSampleStride = mNumPointers * NUM_SAMPLE_DATA; - incrementNumSamplesAndReserveStorage(dataSampleStride); - - mEventTimeNanoSamples[mLastEventTimeNanoSampleIndex] = eventTime * MS_PER_NS; - setPointerCoordsAtSampleIndex(mLastDataSampleIndex, pointerCoords); - - mMetaState |= metaState; + nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pointerCoords, metaState); } @Override public String toString() { return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this)) + " pointerId=" + getPointerId(0) - + " action=" + actionToString(mAction) + + " action=" + actionToString(getAction()) + " x=" + getX() + " y=" + getY() + " pressure=" + getPressure() @@ -1569,13 +1692,13 @@ public final class MotionEvent extends InputEvent implements Parcelable { + " toolMajor=" + getToolMajor() + " toolMinor=" + getToolMinor() + " orientation=" + getOrientation() - + " meta=" + KeyEvent.metaStateToString(mMetaState) + + " meta=" + KeyEvent.metaStateToString(getMetaState()) + " pointerCount=" + getPointerCount() + " historySize=" + getHistorySize() - + " flags=0x" + Integer.toHexString(mFlags) - + " edgeFlags=0x" + Integer.toHexString(mEdgeFlags) - + " device=" + mDeviceId - + " source=0x" + Integer.toHexString(mSource) + + " flags=0x" + Integer.toHexString(getFlags()) + + " edgeFlags=0x" + Integer.toHexString(getEdgeFlags()) + + " device=" + getDeviceId() + + " source=0x" + Integer.toHexString(getSource()) + (getPointerCount() > 1 ? " pointerId2=" + getPointerId(1) + " x2=" + getX(1) + " y2=" + getY(1) : "") + "}"; @@ -1583,7 +1706,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** * Returns a string that represents the symbolic name of the specified action - * such as "ACTION_DOWN", "ACTION_POINTER_DOWN(3)" or "35" (if unknown). + * such as "ACTION_DOWN", "ACTION_POINTER_DOWN(3)" or an equivalent numeric constant + * such as "35" if unknown. * * @param action The action. * @return The symbolic name of the specified action. @@ -1611,6 +1735,39 @@ public final class MotionEvent extends InputEvent implements Parcelable { } } + /** + * Returns a string that represents the symbolic name of the specified axis + * such as "AXIS_X" or an equivalent numeric constants such as "42" if unknown. + * + * @param axis The axis + * @return The symbolic name of the specified axis. + * @hide + */ + public static String axisToString(int axis) { + switch (axis) { + case AXIS_X: + return "AXIS_X"; + case AXIS_Y: + return "AXIS_Y"; + case AXIS_PRESSURE: + return "AXIS_PRESSURE"; + case AXIS_SIZE: + return "AXIS_SIZE"; + case AXIS_TOUCH_MAJOR: + return "AXIS_TOUCH_MAJOR"; + case AXIS_TOUCH_MINOR: + return "AXIS_TOUCH_MINOR"; + case AXIS_TOOL_MAJOR: + return "AXIS_TOOL_MAJOR"; + case AXIS_TOOL_MINOR: + return "AXIS_TOOL_MINOR"; + case AXIS_ORIENTATION: + return "AXIS_ORIENTATION"; + default: + return Integer.toString(axis); + } + } + public static final Parcelable.Creator<MotionEvent> CREATOR = new Parcelable.Creator<MotionEvent>() { public MotionEvent createFromParcel(Parcel in) { @@ -1625,84 +1782,16 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** @hide */ public static MotionEvent createFromParcelBody(Parcel 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.readBaseFromParcel(in); - - 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.mEdgeFlags = in.readInt(); - ev.mMetaState = in.readInt(); - ev.mFlags = 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; + MotionEvent ev = obtain(); + ev.mNativePtr = nativeReadFromParcel(ev.mNativePtr, in); return ev; } - + public void writeToParcel(Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_MOTION_EVENT); - - final int NP = mNumPointers; - final int NS = mNumSamples; - final int NI = NP * NS * NUM_SAMPLE_DATA; - - out.writeInt(NP); - out.writeInt(NS); - - writeBaseToParcel(out); - - out.writeLong(mDownTimeNano); - out.writeInt(mAction); - out.writeFloat(mXOffset); - out.writeFloat(mYOffset); - out.writeFloat(mXPrecision); - out.writeFloat(mYPrecision); - out.writeInt(mEdgeFlags); - out.writeInt(mMetaState); - out.writeInt(mFlags); - - final int[] pointerIdentifiers = mPointerIdentifiers; - for (int i = 0; i < NP; i++) { - out.writeInt(pointerIdentifiers[i]); - } - - 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]); - } + nativeWriteToParcel(mNativePtr, out); } - + /** * Transfer object for pointer coordinates. * @@ -1713,49 +1802,87 @@ public final class MotionEvent extends InputEvent implements Parcelable { * input devices and sources represent pointer coordinates. */ public static final class PointerCoords { + private static final int INITIAL_PACKED_AXIS_VALUES = 8; + private int mPackedAxisBits; // 32bits are enough for now, can raise to 64bit when needed + private float[] mPackedAxisValues; + + /** + * Creates a pointer coords object with all axes initialized to zero. + */ + public PointerCoords() { + } + + /** + * Creates a pointer coords object as a copy of the + * contents of another pointer coords object. + * + * @param other The pointer coords object to copy. + */ + public PointerCoords(PointerCoords other) { + copyFrom(other); + } + /** * The X coordinate of the pointer movement. - * The interpretation varies by input source and may represent the position of - * the center of the contact area, a relative displacement in device-specific units - * or something else. + * The interpretation of the X axis varies by input source. + * It may represent the X position of the center of the touch contact area, + * a relative horizontal displacement of a trackball or joystick, or something else. + * + * @see MotionEvent#AXIS_X */ public float x; /** * The Y coordinate of the pointer movement. - * The interpretation varies by input source and may represent the position of - * the center of the contact area, a relative displacement in device-specific units - * or something else. + * The interpretation of the Y axis varies by input source. + * It may represent the Y position of the center of the touch contact area, + * a relative vertical displacement of a trackball or joystick, or something else. + * + * @see MotionEvent#AXIS_Y */ public float y; /** - * A scaled value that describes the pressure applied to the pointer. + * A normalized value that describes the pressure applied to the device + * by a finger or other tool. * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), - * however values higher than 1 may be generated depending on the calibration of + * although values higher than 1 may be generated depending on the calibration of * the input device. + * + * @see MotionEvent#AXIS_PRESSURE */ public float pressure; /** - * A scaled value of the approximate size of the pointer touch area. - * This represents some approximation of the area of the screen being + * A normalized value that describes the approximate size of the pointer touch area + * in relation to the maximum detectable size of the device. + * It represents some approximation of the area of the screen being * pressed; the actual value in pixels corresponding to the * touch is normalized with the device specific range of values * and scaled to a value between 0 and 1. The value of size can be used to * determine fat touch events. + * + * @see MotionEvent#AXIS_SIZE */ public float size; /** * The length of the major axis of an ellipse that describes the touch area at * the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see MotionEvent#AXIS_TOUCH_MAJOR */ public float touchMajor; /** * The length of the minor axis of an ellipse that describes the touch area at * the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see MotionEvent#AXIS_TOUCH_MINOR */ public float touchMinor; @@ -1764,6 +1891,10 @@ public final class MotionEvent extends InputEvent implements Parcelable { * the approaching tool. * The tool area represents the estimated size of the finger or pen that is * touching the device independent of its actual touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see MotionEvent#AXIS_TOOL_MAJOR */ public float toolMajor; @@ -1772,6 +1903,10 @@ public final class MotionEvent extends InputEvent implements Parcelable { * the approaching tool. * The tool area represents the estimated size of the finger or pen that is * touching the device independent of its actual touch area at the point of contact. + * If the device is a touch screen, the length is reported in pixels, otherwise it is + * reported in device-specific units. + * + * @see MotionEvent#AXIS_TOOL_MINOR */ public float toolMinor; @@ -1783,27 +1918,168 @@ public final class MotionEvent extends InputEvent implements Parcelable { * indicates that the major axis of contact is oriented to the left. * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians * (finger pointing fully right). + * + * @see MotionEvent#AXIS_ORIENTATION */ public float orientation; - - /* - private static final float PI_4 = (float) (Math.PI / 4); - - public float getTouchWidth() { - return Math.abs(orientation) > PI_4 ? touchMajor : touchMinor; + + /** + * Clears the contents of this object. + * Resets all axes to zero. + */ + public void clear() { + mPackedAxisBits = 0; + + x = 0; + y = 0; + pressure = 0; + size = 0; + touchMajor = 0; + touchMinor = 0; + toolMajor = 0; + toolMinor = 0; + orientation = 0; } - - public float getTouchHeight() { - return Math.abs(orientation) > PI_4 ? touchMinor : touchMajor; + + /** + * Copies the contents of another pointer coords object. + * + * @param other The pointer coords object to copy. + */ + public void copyFrom(PointerCoords other) { + final int bits = other.mPackedAxisBits; + mPackedAxisBits = bits; + if (bits != 0) { + final float[] otherValues = other.mPackedAxisValues; + final int count = Integer.bitCount(bits); + float[] values = mPackedAxisValues; + if (values == null || count > values.length) { + values = new float[otherValues.length]; + mPackedAxisValues = values; + } + System.arraycopy(otherValues, 0, values, 0, count); + } + + x = other.x; + y = other.y; + pressure = other.pressure; + size = other.size; + touchMajor = other.touchMajor; + touchMinor = other.touchMinor; + toolMajor = other.toolMajor; + toolMinor = other.toolMinor; + orientation = other.orientation; } - - public float getToolWidth() { - return Math.abs(orientation) > PI_4 ? toolMajor : toolMinor; + + /** + * Gets the value associated with the specified axis. + * + * @param axis The axis identifier for the axis value to retrieve. + * @return The value associated with the axis, or 0 if none. + * + * @see MotionEvent#AXIS_X + * @see MotionEvent#AXIS_Y + */ + public float getAxisValue(int axis) { + switch (axis) { + case AXIS_X: + return x; + case AXIS_Y: + return y; + case AXIS_PRESSURE: + return pressure; + case AXIS_SIZE: + return size; + case AXIS_TOUCH_MAJOR: + return touchMajor; + case AXIS_TOUCH_MINOR: + return touchMinor; + case AXIS_TOOL_MAJOR: + return toolMajor; + case AXIS_TOOL_MINOR: + return toolMinor; + case AXIS_ORIENTATION: + return orientation; + default: { + final int bits = mPackedAxisBits; + final int axisBit = 1 << axis; + if ((bits & axisBit) == 0) { + return 0; + } + final int index = Integer.bitCount(bits & (axisBit - 1)); + return mPackedAxisValues[index]; + } + } } - - public float getToolHeight() { - return Math.abs(orientation) > PI_4 ? toolMinor : toolMajor; + + /** + * Sets the value associated with the specified axis. + * + * @param axis The axis identifier for the axis value to assign. + * @param value The value to set. + * + * @see MotionEvent#AXIS_X + * @see MotionEvent#AXIS_Y + */ + public void setAxisValue(int axis, float value) { + switch (axis) { + case AXIS_X: + x = value; + break; + case AXIS_Y: + y = value; + break; + case AXIS_PRESSURE: + pressure = value; + break; + case AXIS_SIZE: + size = value; + break; + case AXIS_TOUCH_MAJOR: + touchMajor = value; + break; + case AXIS_TOUCH_MINOR: + touchMinor = value; + break; + case AXIS_TOOL_MAJOR: + toolMajor = value; + break; + case AXIS_TOOL_MINOR: + toolMinor = value; + break; + case AXIS_ORIENTATION: + orientation = value; + break; + default: { + final int bits = mPackedAxisBits; + final int axisBit = 1 << axis; + final int index = Integer.bitCount(bits & (axisBit - 1)); + float[] values = mPackedAxisValues; + if ((bits & axisBit) == 0) { + if (values == null) { + values = new float[INITIAL_PACKED_AXIS_VALUES]; + mPackedAxisValues = values; + } else { + final int count = Integer.bitCount(bits); + if (count < values.length) { + if (index != count) { + System.arraycopy(values, index, values, index + 1, + count - index); + } + } else { + float[] newValues = new float[count * 2]; + System.arraycopy(values, 0, newValues, 0, index); + System.arraycopy(values, index, newValues, index + 1, + count - index); + values = newValues; + mPackedAxisValues = values; + } + } + mPackedAxisBits = bits | axisBit; + } + values[index] = value; + } + } } - */ } } diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index f32f0ff..99fbbe9 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -22,24 +22,10 @@ #include <utils/Log.h> #include <ui/Input.h> #include "android_view_MotionEvent.h" +#include "android_util_Binder.h" #include "android/graphics/Matrix.h" -#include <math.h> #include "SkMatrix.h" -#include "SkScalar.h" - -// Number of float items per entry in a DVM sample data array -#define NUM_SAMPLE_DATA 9 - -#define SAMPLE_X 0 -#define SAMPLE_Y 1 -#define SAMPLE_PRESSURE 2 -#define SAMPLE_SIZE 3 -#define SAMPLE_TOUCH_MAJOR 4 -#define SAMPLE_TOUCH_MINOR 5 -#define SAMPLE_TOOL_MAJOR 6 -#define SAMPLE_TOOL_MINOR 7 -#define SAMPLE_ORIENTATION 8 namespace android { @@ -52,35 +38,41 @@ static struct { jmethodID obtain; jmethodID recycle; - jfieldID mDeviceId; - jfieldID mSource; - jfieldID mDownTimeNano; - jfieldID mAction; - jfieldID mXOffset; - jfieldID mYOffset; - jfieldID mXPrecision; - jfieldID mYPrecision; - jfieldID mEdgeFlags; - jfieldID mMetaState; - jfieldID mFlags; - jfieldID mNumPointers; - jfieldID mNumSamples; - jfieldID mPointerIdentifiers; - jfieldID mDataSamples; - jfieldID mEventTimeNanoSamples; - jfieldID mLastDataSampleIndex; - jfieldID mLastEventTimeNanoSampleIndex; + jfieldID mNativePtr; } gMotionEventClassInfo; +static struct { + jclass clazz; + + jfieldID mPackedAxisBits; + jfieldID mPackedAxisValues; + jfieldID x; + jfieldID y; + jfieldID pressure; + jfieldID size; + jfieldID touchMajor; + jfieldID touchMinor; + jfieldID toolMajor; + jfieldID toolMinor; + jfieldID orientation; +} gPointerCoordsClassInfo; + // ---------------------------------------------------------------------------- -jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event) { - jint numPointers = jint(event->getPointerCount()); - jint numHistoricalSamples = jint(event->getHistorySize()); - jint numSamples = numHistoricalSamples + 1; +static MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) { + return reinterpret_cast<MotionEvent*>( + env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr)); +} +static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj, + MotionEvent* event) { + env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr, + reinterpret_cast<int>(event)); +} + +jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event) { jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz, - gMotionEventClassInfo.obtain, numPointers, numSamples); + gMotionEventClassInfo.obtain); if (env->ExceptionCheck()) { LOGE("An exception occurred while obtaining a motion event."); LOGE_EX(env); @@ -88,261 +80,648 @@ jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* even return NULL; } - env->SetIntField(eventObj, gMotionEventClassInfo.mDeviceId, - event->getDeviceId()); - env->SetIntField(eventObj, gMotionEventClassInfo.mSource, - event->getSource()); - env->SetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano, - event->getDownTime()); - env->SetIntField(eventObj, gMotionEventClassInfo.mAction, - event->getAction()); - 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, - event->getYPrecision()); - env->SetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags, - event->getEdgeFlags()); - env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState, - event->getMetaState()); - env->SetIntField(eventObj, gMotionEventClassInfo.mFlags, - event->getFlags()); - env->SetIntField(eventObj, gMotionEventClassInfo.mNumPointers, - 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 eventTimeNanoSampleArray = jlongArray(env->GetObjectField(eventObj, - gMotionEventClassInfo.mEventTimeNanoSamples)); - - jint* pointerIdentifiers = (jint*)env->GetPrimitiveArrayCritical(pointerIdentifierArray, NULL); - jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL); - jlong* eventTimeNanoSamples = (jlong*)env->GetPrimitiveArrayCritical( - eventTimeNanoSampleArray, NULL); - - const int32_t* srcPointerIdentifiers = event->getPointerIds(); - jint* destPointerIdentifiers = pointerIdentifiers; - for (jint i = 0; i < numPointers; i++) { - *(destPointerIdentifiers++) = *(srcPointerIdentifiers++); - } - - const nsecs_t* srcSampleEventTimes = event->getSampleEventTimes(); - jlong* destEventTimeNanoSamples = eventTimeNanoSamples; - for (jint i = 0; i < numSamples; i++) { - *(destEventTimeNanoSamples++) = *(srcSampleEventTimes++); - } - - 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; - *(destDataSamples++) = srcSamplePointerCoords->touchMajor; - *(destDataSamples++) = srcSamplePointerCoords->touchMinor; - *(destDataSamples++) = srcSamplePointerCoords->toolMajor; - *(destDataSamples++) = srcSamplePointerCoords->toolMinor; - *(destDataSamples++) = srcSamplePointerCoords->orientation; - srcSamplePointerCoords += 1; - } - - env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, 0); - env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, 0); - env->ReleasePrimitiveArrayCritical(eventTimeNanoSampleArray, eventTimeNanoSamples, 0); - - env->DeleteLocalRef(pointerIdentifierArray); - env->DeleteLocalRef(dataSampleArray); - env->DeleteLocalRef(eventTimeNanoSampleArray); + MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj); + if (!destEvent) { + destEvent = new MotionEvent(); + android_view_MotionEvent_setNativePtr(env, eventObj, destEvent); + } + + destEvent->copyFrom(event, true); return eventObj; } status_t android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, MotionEvent* event) { - jint deviceId = env->GetIntField(eventObj, gMotionEventClassInfo.mDeviceId); - jint source = env->GetIntField(eventObj, gMotionEventClassInfo.mSource); - jlong downTimeNano = env->GetLongField(eventObj, gMotionEventClassInfo.mDownTimeNano); - jint action = env->GetIntField(eventObj, gMotionEventClassInfo.mAction); - 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 edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags); - jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState); - jint flags = env->GetIntField(eventObj, gMotionEventClassInfo.mFlags); - jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers); - jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples); - - if (numPointers == 0) { - LOGE("Malformed MotionEvent: mNumPointers was zero"); + MotionEvent* srcEvent = android_view_MotionEvent_getNativePtr(env, eventObj); + if (!srcEvent) { + LOGE("MotionEvent was finalized"); return BAD_VALUE; } - if (numSamples == 0) { - LOGE("Malformed MotionEvent: mNumSamples was zero"); - return BAD_VALUE; + + event->copyFrom(srcEvent, true); + return OK; +} + +status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) { + env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle); + if (env->ExceptionCheck()) { + LOGW("An exception occurred while recycling a motion event."); + LOGW_EX(env); + env->ExceptionClear(); + return UNKNOWN_ERROR; + } + return OK; +} + +// ---------------------------------------------------------------------------- + +static const jint HISTORY_CURRENT = -0x80000000; + +static bool validatePointerCount(JNIEnv* env, jint pointerCount) { + if (pointerCount < 1) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerCount must be at least 1"); + return false; + } + return true; +} + +static bool validatePointerIdsArray(JNIEnv* env, jintArray pointerIdsArray, + size_t pointerCount) { + if (!pointerIdsArray) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerIds array must not be null"); + return false; + } + size_t length = size_t(env->GetArrayLength(pointerIdsArray)); + if (length < pointerCount) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerIds array must be large enough to hold all pointers"); + return false; + } + return true; +} + +static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray, + size_t pointerCount) { + if (!pointerCoordsObjArray) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerCoords array must not be null"); + return false; + } + size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray)); + if (length < pointerCount) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerCoords array must be large enough to hold all pointers"); + return false; + } + return true; +} + +static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) { + if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerIndex out of range"); + return false; + } + return true; +} + +static bool validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) { + if (historyPos < 0 || size_t(historyPos) >= historySize) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "historyPos out of range"); + return false; + } + return true; +} + +static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) { + if (!pointerCoordsObj) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "pointerCoords must not be null"); + return false; + } + return true; +} + +static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj, + float xOffset, float yOffset, PointerCoords* outRawPointerCoords) { + outRawPointerCoords->clear(); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_X, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_Y, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_SIZE, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor)); + outRawPointerCoords->setAxisValue(AINPUT_MOTION_AXIS_ORIENTATION, + env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation)); + + uint32_t bits = env->GetIntField(pointerCoordsObj, + gPointerCoordsClassInfo.mPackedAxisBits); + if (bits) { + jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj, + gPointerCoordsClassInfo.mPackedAxisValues)); + if (valuesArray) { + jfloat* values = static_cast<jfloat*>( + env->GetPrimitiveArrayCritical(valuesArray, NULL)); + + uint32_t index = 0; + do { + uint32_t axis = __builtin_ctz(bits); + uint32_t axisBit = 1 << axis; + bits &= ~axisBit; + outRawPointerCoords->setAxisValue(axis, values[index++]); + } while (bits); + + env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT); + env->DeleteLocalRef(valuesArray); + } + } +} + +static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize, + jobject outPointerCoordsObj) { + jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj, + gPointerCoordsClassInfo.mPackedAxisValues)); + if (outValuesArray) { + uint32_t size = env->GetArrayLength(outValuesArray); + if (minSize <= size) { + return outValuesArray; + } + env->DeleteLocalRef(outValuesArray); + } + uint32_t size = 8; + while (size < minSize) { + size *= 2; + } + outValuesArray = env->NewFloatArray(size); + env->SetObjectField(outPointerCoordsObj, + gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray); + return outValuesArray; +} + +static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords, + float xOffset, float yOffset, jobject outPointerCoordsObj) { + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_X) + xOffset); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_Y) + yOffset); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_PRESSURE)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_SIZE)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR)); + env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation, + rawPointerCoords->getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION)); + + const uint32_t unpackedAxisBits = 0 + | (1 << AINPUT_MOTION_AXIS_X) + | (1 << AINPUT_MOTION_AXIS_Y) + | (1 << AINPUT_MOTION_AXIS_PRESSURE) + | (1 << AINPUT_MOTION_AXIS_SIZE) + | (1 << AINPUT_MOTION_AXIS_TOUCH_MAJOR) + | (1 << AINPUT_MOTION_AXIS_TOUCH_MINOR) + | (1 << AINPUT_MOTION_AXIS_TOOL_MAJOR) + | (1 << AINPUT_MOTION_AXIS_TOOL_MINOR) + | (1 << AINPUT_MOTION_AXIS_ORIENTATION); + + uint32_t outBits = 0; + uint32_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits; + if (remainingBits) { + uint32_t packedAxesCount = __builtin_popcount(remainingBits); + jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount, + outPointerCoordsObj); + if (!outValuesArray) { + return; // OOM + } + + jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical( + outValuesArray, NULL)); + + const float* values = rawPointerCoords->values; + uint32_t index = 0; + do { + uint32_t axis = __builtin_ctz(remainingBits); + uint32_t axisBit = 1 << axis; + remainingBits &= ~axisBit; + outBits |= axisBit; + outValues[index++] = rawPointerCoords->getAxisValue(axis); + } while (remainingBits); + + env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0); + env->DeleteLocalRef(outValuesArray); } + env->SetIntField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits); +} - jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj, - gMotionEventClassInfo.mPointerIdentifiers)); - jfloatArray dataSampleArray = jfloatArray(env->GetObjectField(eventObj, - gMotionEventClassInfo.mDataSamples)); - jlongArray eventTimeNanoSampleArray = jlongArray(env->GetObjectField(eventObj, - gMotionEventClassInfo.mEventTimeNanoSamples)); - jint* pointerIdentifiers = (jint*)env->GetPrimitiveArrayCritical(pointerIdentifierArray, NULL); - jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL); - jlong* eventTimeNanoSamples = (jlong*)env->GetPrimitiveArrayCritical( - eventTimeNanoSampleArray, NULL); +// ---------------------------------------------------------------------------- - jfloat* srcDataSamples = dataSamples; - jlong* srcEventTimeNanoSamples = eventTimeNanoSamples; +static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz, + jint nativePtr, + jint deviceId, jint source, jint action, jint flags, jint edgeFlags, jint metaState, + jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision, + jlong downTimeNanos, jlong eventTimeNanos, + jint pointerCount, jintArray pointerIdsArray, jobjectArray pointerCoordsObjArray) { + if (!validatePointerCount(env, pointerCount) + || !validatePointerIdsArray(env, pointerIdsArray, pointerCount) + || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) { + return 0; + } - jlong sampleEventTime = *(srcEventTimeNanoSamples++); - PointerCoords samplePointerCoords[MAX_POINTERS]; - for (jint j = 0; j < numPointers; j++) { - samplePointerCoords[j].x = *(srcDataSamples++); - samplePointerCoords[j].y = *(srcDataSamples++); - samplePointerCoords[j].pressure = *(srcDataSamples++); - samplePointerCoords[j].size = *(srcDataSamples++); - samplePointerCoords[j].touchMajor = *(srcDataSamples++); - samplePointerCoords[j].touchMinor = *(srcDataSamples++); - samplePointerCoords[j].toolMajor = *(srcDataSamples++); - samplePointerCoords[j].toolMinor = *(srcDataSamples++); - samplePointerCoords[j].orientation = *(srcDataSamples++); + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + if (!event) { + event = new MotionEvent(); } + PointerCoords rawPointerCoords[pointerCount]; + + for (jint i = 0; i < pointerCount; i++) { + jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i); + if (!pointerCoordsObj) { + jniThrowNullPointerException(env, "pointerCoords"); + if (!nativePtr) { + delete event; + } + return 0; + } + pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]); + env->DeleteLocalRef(pointerCoordsObj); + } + + int* pointerIds = static_cast<int*>(env->GetPrimitiveArrayCritical(pointerIdsArray, NULL)); + event->initialize(deviceId, source, action, flags, edgeFlags, metaState, - xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime, - numPointers, pointerIdentifiers, samplePointerCoords); - - for (jint i = 1; i < numSamples; i++) { - sampleEventTime = *(srcEventTimeNanoSamples++); - for (jint j = 0; j < numPointers; j++) { - samplePointerCoords[j].x = *(srcDataSamples++); - samplePointerCoords[j].y = *(srcDataSamples++); - samplePointerCoords[j].pressure = *(srcDataSamples++); - samplePointerCoords[j].size = *(srcDataSamples++); - samplePointerCoords[j].touchMajor = *(srcDataSamples++); - samplePointerCoords[j].touchMinor = *(srcDataSamples++); - samplePointerCoords[j].toolMajor = *(srcDataSamples++); - samplePointerCoords[j].toolMinor = *(srcDataSamples++); - samplePointerCoords[j].orientation = *(srcDataSamples++); + xOffset, yOffset, xPrecision, yPrecision, + downTimeNanos, eventTimeNanos, pointerCount, pointerIds, rawPointerCoords); + + env->ReleasePrimitiveArrayCritical(pointerIdsArray, pointerIds, JNI_ABORT); + return reinterpret_cast<jint>(event); +} + +static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz, + jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) { + MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr); + if (!destEvent) { + destEvent = new MotionEvent(); + } + MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr); + destEvent->copyFrom(sourceEvent, keepHistory); + return reinterpret_cast<jint>(destEvent); +} + +static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + delete event; +} + +static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz, + jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray, + jint metaState) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) { + return; + } + + PointerCoords rawPointerCoords[pointerCount]; + + for (size_t i = 0; i < pointerCount; i++) { + jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i); + if (!pointerCoordsObj) { + jniThrowNullPointerException(env, "pointerCoords"); + return; } - event->addSample(sampleEventTime, samplePointerCoords); + pointerCoordsToNative(env, pointerCoordsObj, + event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]); + env->DeleteLocalRef(pointerCoordsObj); } - env->ReleasePrimitiveArrayCritical(eventTimeNanoSampleArray, eventTimeNanoSamples, JNI_ABORT); - env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, JNI_ABORT); - env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, JNI_ABORT); + event->addSample(eventTimeNanos, rawPointerCoords); + event->setMetaState(event->getMetaState() | metaState); +} - env->DeleteLocalRef(eventTimeNanoSampleArray); - env->DeleteLocalRef(dataSampleArray); - env->DeleteLocalRef(pointerIdentifierArray); - return OK; +static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getDeviceId(); } -status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) { - env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle); - if (env->ExceptionCheck()) { - LOGW("An exception occurred while recycling a motion event."); - LOGW_EX(env); - env->ExceptionClear(); - return UNKNOWN_ERROR; +static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getSource(); +} + +static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz, + jint nativePtr, jint source) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + event->setSource(source); +} + +static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getAction(); +} + +static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz, + jint nativePtr, jint action) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + event->setAction(action); +} + +static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getFlags(); +} + +static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getEdgeFlags(); +} + +static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz, + jint nativePtr, jint edgeFlags) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + event->setEdgeFlags(edgeFlags); +} + +static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getMetaState(); +} + +static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz, + jint nativePtr, jfloat deltaX, jfloat deltaY) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->offsetLocation(deltaX, deltaY); +} + +static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getXPrecision(); +} + +static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getYPrecision(); +} + +static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return event->getDownTime(); +} + +static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return jint(event->getPointerCount()); +} + +static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz, + jint nativePtr, jint pointerIndex) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + if (!validatePointerIndex(env, pointerIndex, pointerCount)) { + return -1; } - return OK; + return event->getPointerId(pointerIndex); } -static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { - // Construct and transform a vector oriented at the specified clockwise angle from vertical. - // Coordinate system: down is increasing Y, right is increasing X. - SkPoint vector; - vector.fX = SkFloatToScalar(sinf(angleRadians)); - vector.fY = SkFloatToScalar(- cosf(angleRadians)); - matrix->mapVectors(& vector, 1); +static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz, + jint nativePtr, jint pointerId) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + for (size_t i = 0; i < pointerCount; i++) { + if (event->getPointerId(i) == pointerId) { + return i; + } + } + return -1; +} + +static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz, + jint nativePtr) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + return jint(event->getHistorySize()); +} - // Derive the transformed vector's clockwise angle from vertical. - float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(- vector.fY)); - if (result < - M_PI_2) { - result += M_PI; - } else if (result > M_PI_2) { - result -= M_PI; +static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz, + jint nativePtr, jint historyPos) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + if (historyPos == HISTORY_CURRENT) { + return event->getEventTime(); + } else { + size_t historySize = event->getHistorySize(); + if (!validateHistoryPos(env, historyPos, historySize)) { + return 0; + } + return event->getHistoricalEventTime(historyPos); } - return result; } -static void android_view_MotionEvent_nativeTransform(JNIEnv* env, - jobject eventObj, jobject matrixObj) { - SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj); +static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz, + jint nativePtr, jint axis, jint pointerIndex, jint historyPos) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + if (!validatePointerIndex(env, pointerIndex, pointerCount)) { + return 0; + } - jfloat oldXOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mXOffset); - jfloat oldYOffset = env->GetFloatField(eventObj, gMotionEventClassInfo.mYOffset); - jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers); - jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples); - jfloatArray dataSampleArray = jfloatArray(env->GetObjectField(eventObj, - gMotionEventClassInfo.mDataSamples)); - jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL); - - // The tricky part of this implementation is to preserve the value of - // rawX and rawY. So we apply the transformation to the first point - // then derive an appropriate new X/Y offset that will preserve rawX and rawY. - SkPoint point; - jfloat rawX = dataSamples[SAMPLE_X]; - jfloat rawY = dataSamples[SAMPLE_Y]; - matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), - & point); - jfloat newX = SkScalarToFloat(point.fX); - jfloat newY = SkScalarToFloat(point.fY); - jfloat newXOffset = newX - rawX; - jfloat newYOffset = newY - rawY; - - dataSamples[SAMPLE_ORIENTATION] = transformAngle(matrix, dataSamples[SAMPLE_ORIENTATION]); - - // Apply the transformation to all samples. - jfloat* currentDataSample = dataSamples; - jfloat* endDataSample = dataSamples + numPointers * numSamples * NUM_SAMPLE_DATA; - for (;;) { - currentDataSample += NUM_SAMPLE_DATA; - if (currentDataSample == endDataSample) { - break; + if (historyPos == HISTORY_CURRENT) { + return event->getRawAxisValue(axis, pointerIndex); + } else { + size_t historySize = event->getHistorySize(); + if (!validateHistoryPos(env, historyPos, historySize)) { + return 0; } + return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos); + } +} - jfloat x = currentDataSample[SAMPLE_X] + oldXOffset; - jfloat y = currentDataSample[SAMPLE_Y] + oldYOffset; - matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point); - currentDataSample[SAMPLE_X] = SkScalarToFloat(point.fX) - newXOffset; - currentDataSample[SAMPLE_Y] = SkScalarToFloat(point.fY) - newYOffset; +static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz, + jint nativePtr, jint axis, jint pointerIndex, jint historyPos) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + if (!validatePointerIndex(env, pointerIndex, pointerCount)) { + return 0; + } - currentDataSample[SAMPLE_ORIENTATION] = transformAngle(matrix, - currentDataSample[SAMPLE_ORIENTATION]); + if (historyPos == HISTORY_CURRENT) { + return event->getAxisValue(axis, pointerIndex); + } else { + size_t historySize = event->getHistorySize(); + if (!validateHistoryPos(env, historyPos, historySize)) { + return 0; + } + return event->getHistoricalAxisValue(axis, pointerIndex, historyPos); } +} - env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, 0); +static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz, + jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + size_t pointerCount = event->getPointerCount(); + if (!validatePointerIndex(env, pointerIndex, pointerCount) + || !validatePointerCoords(env, outPointerCoordsObj)) { + return; + } - env->SetFloatField(eventObj, gMotionEventClassInfo.mXOffset, newXOffset); - env->SetFloatField(eventObj, gMotionEventClassInfo.mYOffset, newYOffset); + const PointerCoords* rawPointerCoords; + if (historyPos == HISTORY_CURRENT) { + rawPointerCoords = event->getRawPointerCoords(pointerIndex); + } else { + size_t historySize = event->getHistorySize(); + if (!validateHistoryPos(env, historyPos, historySize)) { + return; + } + rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos); + } + pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(), + outPointerCoordsObj); +} + +static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz, + jint nativePtr, jfloat scale) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + event->scale(scale); +} + +static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz, + jint nativePtr, jobject matrixObj) { + SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj); + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + event->transform(matrix); +} + +static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz, + jint nativePtr, jobject parcelObj) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + if (!event) { + event = new MotionEvent(); + } + + Parcel* parcel = parcelForJavaObject(env, parcelObj); - env->DeleteLocalRef(dataSampleArray); + status_t status = event->readFromParcel(parcel); + if (!status) { + if (!nativePtr) { + delete event; + } + jniThrowRuntimeException(env, "Failed to read MotionEvent parcel."); + return 0; + } + return reinterpret_cast<jint>(event); +} + +static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz, + jint nativePtr, jobject parcelObj) { + MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr); + Parcel* parcel = parcelForJavaObject(env, parcelObj); + + status_t status = event->writeToParcel(parcel); + if (!status) { + jniThrowRuntimeException(env, "Failed to write MotionEvent parcel."); + } } // ---------------------------------------------------------------------------- static JNINativeMethod gMotionEventMethods[] = { /* name, signature, funcPtr */ + { "nativeInitialize", + "(IIIIIIIFFFFJJI[I[Landroid/view/MotionEvent$PointerCoords;)I", + (void*)android_view_MotionEvent_nativeInitialize }, + { "nativeCopy", + "(IIZ)I", + (void*)android_view_MotionEvent_nativeCopy }, + { "nativeDispose", + "(I)V", + (void*)android_view_MotionEvent_nativeDispose }, + { "nativeAddBatch", + "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V", + (void*)android_view_MotionEvent_nativeAddBatch }, + { "nativeGetDeviceId", + "(I)I", + (void*)android_view_MotionEvent_nativeGetDeviceId }, + { "nativeGetSource", + "(I)I", + (void*)android_view_MotionEvent_nativeGetSource }, + { "nativeSetSource", + "(II)I", + (void*)android_view_MotionEvent_nativeSetSource }, + { "nativeGetAction", + "(I)I", + (void*)android_view_MotionEvent_nativeGetAction }, + { "nativeSetAction", + "(II)V", + (void*)android_view_MotionEvent_nativeSetAction }, + { "nativeGetFlags", + "(I)I", + (void*)android_view_MotionEvent_nativeGetFlags }, + { "nativeGetEdgeFlags", + "(I)I", + (void*)android_view_MotionEvent_nativeGetEdgeFlags }, + { "nativeSetEdgeFlags", + "(II)V", + (void*)android_view_MotionEvent_nativeSetEdgeFlags }, + { "nativeGetMetaState", + "(I)I", + (void*)android_view_MotionEvent_nativeGetMetaState }, + { "nativeOffsetLocation", + "(IFF)V", + (void*)android_view_MotionEvent_nativeOffsetLocation }, + { "nativeGetXPrecision", + "(I)F", + (void*)android_view_MotionEvent_nativeGetXPrecision }, + { "nativeGetYPrecision", + "(I)F", + (void*)android_view_MotionEvent_nativeGetYPrecision }, + { "nativeGetDownTimeNanos", + "(I)J", + (void*)android_view_MotionEvent_nativeGetDownTimeNanos }, + { "nativeGetPointerCount", + "(I)I", + (void*)android_view_MotionEvent_nativeGetPointerCount }, + { "nativeGetPointerId", + "(II)I", + (void*)android_view_MotionEvent_nativeGetPointerId }, + { "nativeFindPointerIndex", + "(II)I", + (void*)android_view_MotionEvent_nativeFindPointerIndex }, + { "nativeGetHistorySize", + "(I)I", + (void*)android_view_MotionEvent_nativeGetHistorySize }, + { "nativeGetEventTimeNanos", + "(II)J", + (void*)android_view_MotionEvent_nativeGetEventTimeNanos }, + { "nativeGetRawAxisValue", + "(IIII)F", + (void*)android_view_MotionEvent_nativeGetRawAxisValue }, + { "nativeGetAxisValue", + "(IIII)F", + (void*)android_view_MotionEvent_nativeGetAxisValue }, + { "nativeGetPointerCoords", + "(IIILandroid/view/MotionEvent$PointerCoords;)V", + (void*)android_view_MotionEvent_nativeGetPointerCoords }, + { "nativeScale", + "(IF)V", + (void*)android_view_MotionEvent_nativeScale }, { "nativeTransform", - "(Landroid/graphics/Matrix;)V", + "(ILandroid/graphics/Matrix;)V", (void*)android_view_MotionEvent_nativeTransform }, + { "nativeReadFromParcel", + "(ILandroid/os/Parcel;)I", + (void*)android_view_MotionEvent_nativeReadFromParcel }, + { "nativeWriteToParcel", + "(ILandroid/os/Parcel;)V", + (void*)android_view_MotionEvent_nativeWriteToParcel }, }; #define FIND_CLASS(var, className) \ @@ -370,46 +749,36 @@ int register_android_view_MotionEvent(JNIEnv* env) { FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent"); GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz, - "obtain", "(II)Landroid/view/MotionEvent;"); + "obtain", "()Landroid/view/MotionEvent;"); GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz, "recycle", "()V"); - - GET_FIELD_ID(gMotionEventClassInfo.mDeviceId, gMotionEventClassInfo.clazz, - "mDeviceId", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mSource, gMotionEventClassInfo.clazz, - "mSource", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mDownTimeNano, gMotionEventClassInfo.clazz, - "mDownTimeNano", "J"); - GET_FIELD_ID(gMotionEventClassInfo.mAction, gMotionEventClassInfo.clazz, - "mAction", "I"); - 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, - "mYPrecision", "F"); - GET_FIELD_ID(gMotionEventClassInfo.mEdgeFlags, gMotionEventClassInfo.clazz, - "mEdgeFlags", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz, - "mMetaState", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mFlags, gMotionEventClassInfo.clazz, - "mFlags", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mNumPointers, gMotionEventClassInfo.clazz, - "mNumPointers", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mNumSamples, gMotionEventClassInfo.clazz, - "mNumSamples", "I"); - GET_FIELD_ID(gMotionEventClassInfo.mPointerIdentifiers, gMotionEventClassInfo.clazz, - "mPointerIdentifiers", "[I"); - GET_FIELD_ID(gMotionEventClassInfo.mDataSamples, gMotionEventClassInfo.clazz, - "mDataSamples", "[F"); - 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"); + GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz, + "mNativePtr", "I"); + + FIND_CLASS(gPointerCoordsClassInfo.clazz, "android/view/MotionEvent$PointerCoords"); + + GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, gPointerCoordsClassInfo.clazz, + "mPackedAxisBits", "I"); + GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, gPointerCoordsClassInfo.clazz, + "mPackedAxisValues", "[F"); + GET_FIELD_ID(gPointerCoordsClassInfo.x, gPointerCoordsClassInfo.clazz, + "x", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.y, gPointerCoordsClassInfo.clazz, + "y", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.pressure, gPointerCoordsClassInfo.clazz, + "pressure", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.size, gPointerCoordsClassInfo.clazz, + "size", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, gPointerCoordsClassInfo.clazz, + "touchMajor", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, gPointerCoordsClassInfo.clazz, + "touchMinor", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, gPointerCoordsClassInfo.clazz, + "toolMajor", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, gPointerCoordsClassInfo.clazz, + "toolMinor", "F"); + GET_FIELD_ID(gPointerCoordsClassInfo.orientation, gPointerCoordsClassInfo.clazz, + "orientation", "F"); return 0; } diff --git a/include/ui/Input.h b/include/ui/Input.h index 2012fcc..b7b5a8d 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -28,6 +28,10 @@ #include <utils/RefBase.h> #include <utils/String8.h> +#ifdef HAVE_ANDROID_OS +class SkMatrix; +#endif + /* * Additional private constants not defined in ndk/ui/input.h. */ @@ -79,6 +83,10 @@ struct AInputDevice { namespace android { +#ifdef HAVE_ANDROID_OS +class Parcel; +#endif + /* * Flags that flow alongside events in the input dispatch system to help with certain * policy decisions such as waking from device sleep. @@ -162,15 +170,61 @@ struct InputConfiguration { * Pointer coordinate data. */ struct PointerCoords { - float x; - float y; - float pressure; - float size; - float touchMajor; - float touchMinor; - float toolMajor; - float toolMinor; - float orientation; + static const size_t MAX_AXES = 15; // 15 so that sizeof(PointerCoords) == 16 * 4 == 64 + + // Bitfield of axes that are present in this structure. + uint32_t bits; // 32bits are enough for now, can raise to 64bit when needed + + // Values of axes that are stored in this structure packed in order by axis id + // for each axis that is present in the structure according to 'bits'. + float values[MAX_AXES]; + + inline void clear() { + bits = 0; + } + + inline float getAxisValue(int32_t axis) const { + uint32_t axisBit = 1 << axis; + if (!(bits & axisBit)) { + return 0; + } + uint32_t index = __builtin_popcount(bits & (axisBit - 1)); + return values[index]; + } + + inline void setAxisValue(int32_t axis, float value) { + uint32_t axisBit = 1 << axis; + uint32_t index = __builtin_popcount(bits & (axisBit - 1)); + if (!(bits & axisBit)) { + uint32_t count = __builtin_popcount(bits); + if (count >= MAX_AXES) { + tooManyAxes(axis); + return; + } + bits |= axisBit; + for (uint32_t i = count; i > index; i--) { + values[i] = values[i - 1]; + } + } + values[index] = value; + } + + inline float* editAxisValue(int32_t axis) { + uint32_t axisBit = 1 << axis; + if (!(bits & axisBit)) { + return NULL; + } + uint32_t index = __builtin_popcount(bits & (axisBit - 1)); + return &values[index]; + } + +#ifdef HAVE_ANDROID_OS + status_t readFromParcel(Parcel* parcel); + status_t writeToParcel(Parcel* parcel) const; +#endif + +private: + void tooManyAxes(int axis); }; /* @@ -185,12 +239,13 @@ public: inline int32_t getDeviceId() const { return mDeviceId; } inline int32_t getSource() const { return mSource; } - + + inline void setSource(int32_t source) { mSource = source; } + protected: void initialize(int32_t deviceId, int32_t source); void initialize(const InputEvent& from); -private: int32_t mDeviceId; int32_t mSource; }; @@ -241,7 +296,7 @@ public: nsecs_t eventTime); void initialize(const KeyEvent& from); -private: +protected: int32_t mAction; int32_t mFlags; int32_t mKeyCode; @@ -263,12 +318,18 @@ public: inline int32_t getAction() const { return mAction; } + inline void setAction(int32_t action) { mAction = action; } + inline int32_t getFlags() const { return mFlags; } inline int32_t getEdgeFlags() const { return mEdgeFlags; } + inline void setEdgeFlags(int32_t edgeFlags) { mEdgeFlags = edgeFlags; } + inline int32_t getMetaState() const { return mMetaState; } + inline void setMetaState(int32_t metaState) { mMetaState = metaState; } + inline float getXOffset() const { return mXOffset; } inline float getYOffset() const { return mYOffset; } @@ -285,48 +346,54 @@ public: inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; } + const PointerCoords* getRawPointerCoords(size_t pointerIndex) const; + + float getRawAxisValue(int32_t axis, size_t pointerIndex) const; + inline float getRawX(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).x; + return getRawAxisValue(AINPUT_MOTION_AXIS_X, pointerIndex); } inline float getRawY(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).y; + return getRawAxisValue(AINPUT_MOTION_AXIS_Y, pointerIndex); } + float getAxisValue(int32_t axis, size_t pointerIndex) const; + inline float getX(size_t pointerIndex) const { - return getRawX(pointerIndex) + mXOffset; + return getAxisValue(AINPUT_MOTION_AXIS_X, pointerIndex); } inline float getY(size_t pointerIndex) const { - return getRawY(pointerIndex) + mYOffset; + return getAxisValue(AINPUT_MOTION_AXIS_Y, pointerIndex); } inline float getPressure(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).pressure; + return getAxisValue(AINPUT_MOTION_AXIS_PRESSURE, pointerIndex); } inline float getSize(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).size; + return getAxisValue(AINPUT_MOTION_AXIS_SIZE, pointerIndex); } inline float getTouchMajor(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).touchMajor; + return getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR, pointerIndex); } inline float getTouchMinor(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).touchMinor; + return getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR, pointerIndex); } inline float getToolMajor(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).toolMajor; + return getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, pointerIndex); } inline float getToolMinor(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).toolMinor; + return getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR, pointerIndex); } inline float getOrientation(size_t pointerIndex) const { - return getCurrentPointerCoords(pointerIndex).orientation; + return getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION, pointerIndex); } inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; } @@ -335,48 +402,67 @@ public: return mSampleEventTimes[historicalIndex]; } + const PointerCoords* getHistoricalRawPointerCoords( + size_t pointerIndex, size_t historicalIndex) const; + + float getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, + size_t historicalIndex) const; + inline float getHistoricalRawX(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).x; + return getHistoricalRawAxisValue( + AINPUT_MOTION_AXIS_X, pointerIndex, historicalIndex); } inline float getHistoricalRawY(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).y; + return getHistoricalRawAxisValue( + AINPUT_MOTION_AXIS_Y, pointerIndex, historicalIndex); } + float getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const; + inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalRawX(pointerIndex, historicalIndex) + mXOffset; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_X, pointerIndex, historicalIndex); } inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalRawY(pointerIndex, historicalIndex) + mYOffset; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_Y, pointerIndex, historicalIndex); } inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).pressure; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_PRESSURE, pointerIndex, historicalIndex); } inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).size; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_SIZE, pointerIndex, historicalIndex); } inline float getHistoricalTouchMajor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMajor; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_TOUCH_MAJOR, pointerIndex, historicalIndex); } inline float getHistoricalTouchMinor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).touchMinor; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_TOUCH_MINOR, pointerIndex, historicalIndex); } inline float getHistoricalToolMajor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMajor; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_TOOL_MAJOR, pointerIndex, historicalIndex); } inline float getHistoricalToolMinor(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).toolMinor; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_TOOL_MINOR, pointerIndex, historicalIndex); } inline float getHistoricalOrientation(size_t pointerIndex, size_t historicalIndex) const { - return getHistoricalPointerCoords(pointerIndex, historicalIndex).orientation; + return getHistoricalAxisValue( + AINPUT_MOTION_AXIS_ORIENTATION, pointerIndex, historicalIndex); } void initialize( @@ -396,12 +482,23 @@ public: const int32_t* pointerIds, const PointerCoords* pointerCoords); + void copyFrom(const MotionEvent* other, bool keepHistory); + void addSample( nsecs_t eventTime, const PointerCoords* pointerCoords); void offsetLocation(float xOffset, float yOffset); + void scale(float scaleFactor); + +#ifdef HAVE_ANDROID_OS + void transform(const SkMatrix* matrix); + + status_t readFromParcel(Parcel* parcel); + status_t writeToParcel(Parcel* parcel) const; +#endif + // Low-level accessors. inline const int32_t* getPointerIds() const { return mPointerIds.array(); } inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); } @@ -409,7 +506,7 @@ public: return mSamplePointerCoords.array(); } -private: +protected: int32_t mAction; int32_t mFlags; int32_t mEdgeFlags; @@ -422,15 +519,6 @@ private: Vector<int32_t> mPointerIds; Vector<nsecs_t> mSampleEventTimes; Vector<PointerCoords> mSamplePointerCoords; - - inline const PointerCoords& getCurrentPointerCoords(size_t pointerIndex) const { - return mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; - } - - inline const PointerCoords& getHistoricalPointerCoords( - size_t pointerIndex, size_t historicalIndex) const { - return mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; - } }; /* @@ -486,11 +574,11 @@ public: inline const String8 getName() const { return mName; } inline uint32_t getSources() const { return mSources; } - const MotionRange* getMotionRange(int32_t rangeType) const; + const MotionRange* getMotionRange(int32_t axis) const; void addSource(uint32_t source); - void addMotionRange(int32_t rangeType, float min, float max, float flat, float fuzz); - void addMotionRange(int32_t rangeType, const MotionRange& range); + void addMotionRange(int32_t axis, float min, float max, float flat, float fuzz); + void addMotionRange(int32_t axis, const MotionRange& range); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 0d55f08..f9990bb 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -60,7 +60,12 @@ LOCAL_SHARED_LIBRARIES := \ libEGL \ libpixelflinger \ libhardware \ - libhardware_legacy + libhardware_legacy \ + libskia \ + libbinder + +LOCAL_C_INCLUDES := \ + external/skia/include/core LOCAL_MODULE:= libui diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index b8d59e6..90b954e 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -15,6 +15,16 @@ #include <ui/Input.h> +#include <math.h> + +#ifdef HAVE_ANDROID_OS +#include <binder/Parcel.h> + +#include "SkPoint.h" +#include "SkMatrix.h" +#include "SkScalar.h" +#endif + namespace android { static const char* CONFIGURATION_FILE_DIR[] = { @@ -237,6 +247,41 @@ void KeyEvent::initialize(const KeyEvent& from) { mEventTime = from.mEventTime; } + +// --- PointerCoords --- + +#ifdef HAVE_ANDROID_OS +status_t PointerCoords::readFromParcel(Parcel* parcel) { + bits = parcel->readInt32(); + + uint32_t count = __builtin_popcount(bits); + if (count > MAX_AXES) { + return BAD_VALUE; + } + + for (uint32_t i = 0; i < count; i++) { + values[i] = parcel->readInt32(); + } + return OK; +} + +status_t PointerCoords::writeToParcel(Parcel* parcel) const { + parcel->writeInt32(bits); + + uint32_t count = __builtin_popcount(bits); + for (uint32_t i = 0; i < count; i++) { + parcel->writeInt32(values[i]); + } + return OK; +} +#endif + +void PointerCoords::tooManyAxes(int axis) { + LOGW("Could not set value for axis %d because the PointerCoords structure is full and " + "cannot contain more than %d axis values.", axis, int(MAX_AXES)); +} + + // --- MotionEvent --- void MotionEvent::initialize( @@ -272,6 +317,33 @@ void MotionEvent::initialize( addSample(eventTime, pointerCoords); } +void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { + InputEvent::initialize(other->mDeviceId, other->mSource); + mAction = other->mAction; + mFlags = other->mFlags; + mEdgeFlags = other->mEdgeFlags; + mMetaState = other->mMetaState; + mXOffset = other->mXOffset; + mYOffset = other->mYOffset; + mXPrecision = other->mXPrecision; + mYPrecision = other->mYPrecision; + mDownTime = other->mDownTime; + mPointerIds = other->mPointerIds; + + if (keepHistory) { + mSampleEventTimes = other->mSampleEventTimes; + mSamplePointerCoords = other->mSamplePointerCoords; + } else { + mSampleEventTimes.clear(); + mSampleEventTimes.push(other->getEventTime()); + mSamplePointerCoords.clear(); + size_t pointerCount = other->getPointerCount(); + size_t historySize = other->getHistorySize(); + mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() + + (historySize * pointerCount), pointerCount); + } +} + void MotionEvent::addSample( int64_t eventTime, const PointerCoords* pointerCoords) { @@ -279,11 +351,224 @@ void MotionEvent::addSample( mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); } +const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { + return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; +} + +float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { + return getRawPointerCoords(pointerIndex)->getAxisValue(axis); +} + +float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { + float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); + switch (axis) { + case AINPUT_MOTION_AXIS_X: + value += mXOffset; + break; + case AINPUT_MOTION_AXIS_Y: + value += mYOffset; + break; + } + return value; +} + +const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( + size_t pointerIndex, size_t historicalIndex) const { + return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; +} + +float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, + size_t historicalIndex) const { + return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); +} + +float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, + size_t historicalIndex) const { + float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); + switch (axis) { + case AINPUT_MOTION_AXIS_X: + value += mXOffset; + break; + case AINPUT_MOTION_AXIS_Y: + value += mYOffset; + break; + } + return value; +} + void MotionEvent::offsetLocation(float xOffset, float yOffset) { mXOffset += xOffset; mYOffset += yOffset; } +static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { + float* value = c.editAxisValue(axis); + if (value) { + *value *= scaleFactor; + } +} + +void MotionEvent::scale(float scaleFactor) { + mXOffset *= scaleFactor; + mYOffset *= scaleFactor; + mXPrecision *= scaleFactor; + mYPrecision *= scaleFactor; + + size_t numSamples = mSamplePointerCoords.size(); + for (size_t i = 0; i < numSamples; i++) { + PointerCoords& c = mSamplePointerCoords.editItemAt(i); + // No need to scale pressure or size since they are normalized. + // No need to scale orientation since it is meaningless to do so. + scaleAxisValue(c, AINPUT_MOTION_AXIS_X, scaleFactor); + scaleAxisValue(c, AINPUT_MOTION_AXIS_Y, scaleFactor); + scaleAxisValue(c, AINPUT_MOTION_AXIS_TOUCH_MAJOR, scaleFactor); + scaleAxisValue(c, AINPUT_MOTION_AXIS_TOUCH_MINOR, scaleFactor); + scaleAxisValue(c, AINPUT_MOTION_AXIS_TOOL_MAJOR, scaleFactor); + scaleAxisValue(c, AINPUT_MOTION_AXIS_TOOL_MINOR, scaleFactor); + } +} + +#ifdef HAVE_ANDROID_OS +static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { + // Construct and transform a vector oriented at the specified clockwise angle from vertical. + // Coordinate system: down is increasing Y, right is increasing X. + SkPoint vector; + vector.fX = SkFloatToScalar(sinf(angleRadians)); + vector.fY = SkFloatToScalar(-cosf(angleRadians)); + matrix->mapVectors(& vector, 1); + + // Derive the transformed vector's clockwise angle from vertical. + float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); + if (result < - M_PI_2) { + result += M_PI; + } else if (result > M_PI_2) { + result -= M_PI; + } + return result; +} + +void MotionEvent::transform(const SkMatrix* matrix) { + float oldXOffset = mXOffset; + float oldYOffset = mYOffset; + + // The tricky part of this implementation is to preserve the value of + // rawX and rawY. So we apply the transformation to the first point + // then derive an appropriate new X/Y offset that will preserve rawX and rawY. + SkPoint point; + float rawX = getRawX(0); + float rawY = getRawY(0); + matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), + & point); + float newX = SkScalarToFloat(point.fX); + float newY = SkScalarToFloat(point.fY); + float newXOffset = newX - rawX; + float newYOffset = newY - rawY; + + mXOffset = newXOffset; + mYOffset = newYOffset; + + // Apply the transformation to all samples. + size_t numSamples = mSamplePointerCoords.size(); + for (size_t i = 0; i < numSamples; i++) { + PointerCoords& c = mSamplePointerCoords.editItemAt(i); + float* xPtr = c.editAxisValue(AINPUT_MOTION_AXIS_X); + float* yPtr = c.editAxisValue(AINPUT_MOTION_AXIS_Y); + if (xPtr && yPtr) { + float x = *xPtr + oldXOffset; + float y = *yPtr + oldYOffset; + matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point); + *xPtr = SkScalarToFloat(point.fX) - newXOffset; + *yPtr = SkScalarToFloat(point.fY) - newYOffset; + } + + float* orientationPtr = c.editAxisValue(AINPUT_MOTION_AXIS_ORIENTATION); + if (orientationPtr) { + *orientationPtr = transformAngle(matrix, *orientationPtr); + } + } +} + +status_t MotionEvent::readFromParcel(Parcel* parcel) { + size_t pointerCount = parcel->readInt32(); + size_t sampleCount = parcel->readInt32(); + if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { + return BAD_VALUE; + } + + mDeviceId = parcel->readInt32(); + mSource = parcel->readInt32(); + mAction = parcel->readInt32(); + mFlags = parcel->readInt32(); + mEdgeFlags = parcel->readInt32(); + mMetaState = parcel->readInt32(); + mXOffset = parcel->readFloat(); + mYOffset = parcel->readFloat(); + mXPrecision = parcel->readFloat(); + mYPrecision = parcel->readFloat(); + mDownTime = parcel->readInt64(); + + mPointerIds.clear(); + mPointerIds.setCapacity(pointerCount); + mSampleEventTimes.clear(); + mSampleEventTimes.setCapacity(sampleCount); + mSamplePointerCoords.clear(); + mSamplePointerCoords.setCapacity(sampleCount * pointerCount); + + for (size_t i = 0; i < pointerCount; i++) { + mPointerIds.push(parcel->readInt32()); + } + + while (sampleCount-- > 0) { + mSampleEventTimes.push(parcel->readInt64()); + for (size_t i = 0; i < pointerCount; i++) { + mSamplePointerCoords.push(); + status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); + if (!status) { + return status; + } + } + } + return OK; +} + +status_t MotionEvent::writeToParcel(Parcel* parcel) const { + size_t pointerCount = mPointerIds.size(); + size_t sampleCount = mSampleEventTimes.size(); + + parcel->writeInt32(pointerCount); + parcel->writeInt32(sampleCount); + + parcel->writeInt32(mDeviceId); + parcel->writeInt32(mSource); + parcel->writeInt32(mAction); + parcel->writeInt32(mFlags); + parcel->writeInt32(mEdgeFlags); + parcel->writeInt32(mMetaState); + parcel->writeFloat(mXOffset); + parcel->writeFloat(mYOffset); + parcel->writeFloat(mXPrecision); + parcel->writeFloat(mYPrecision); + parcel->writeInt64(mDownTime); + + for (size_t i = 0; i < pointerCount; i++) { + parcel->writeInt32(mPointerIds.itemAt(i)); + } + + const PointerCoords* pc = mSamplePointerCoords.array(); + for (size_t h = 0; h < sampleCount; h++) { + parcel->writeInt64(mSampleEventTimes.itemAt(h)); + for (size_t i = 0; i < pointerCount; i++) { + status_t status = (pc++)->writeToParcel(parcel); + if (!status) { + return status; + } + } + } + return OK; +} +#endif + + // --- InputDeviceInfo --- InputDeviceInfo::InputDeviceInfo() { @@ -307,8 +592,8 @@ void InputDeviceInfo::initialize(int32_t id, const String8& name) { mMotionRanges.clear(); } -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t rangeType) const { - ssize_t index = mMotionRanges.indexOfKey(rangeType); +const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t axis) const { + ssize_t index = mMotionRanges.indexOfKey(axis); return index >= 0 ? & mMotionRanges.valueAt(index) : NULL; } @@ -316,14 +601,14 @@ void InputDeviceInfo::addSource(uint32_t source) { mSources |= source; } -void InputDeviceInfo::addMotionRange(int32_t rangeType, float min, float max, +void InputDeviceInfo::addMotionRange(int32_t axis, float min, float max, float flat, float fuzz) { MotionRange range = { min, max, flat, fuzz }; - addMotionRange(rangeType, range); + addMotionRange(axis, range); } -void InputDeviceInfo::addMotionRange(int32_t rangeType, const MotionRange& range) { - mMotionRanges.add(rangeType, range); +void InputDeviceInfo::addMotionRange(int32_t axis, const MotionRange& range) { + mMotionRanges.add(axis, range); } } // namespace android diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp index 903fcaf..1819a8b 100644 --- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp @@ -159,15 +159,17 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( 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; - samplePointerCoords.editTop().touchMajor = 1.5 * i + j; - samplePointerCoords.editTop().touchMinor = 1.7 * i + j; - samplePointerCoords.editTop().toolMajor = 2.5 * i + j; - samplePointerCoords.editTop().toolMinor = 2.7 * i + j; - samplePointerCoords.editTop().orientation = 3.5 * i + j; + PointerCoords& pc = samplePointerCoords.editTop(); + pc.clear(); + pc.setAxisValue(AINPUT_MOTION_AXIS_X, 100 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_Y, 200 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, 0.5 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_SIZE, 0.7 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR, 1.5 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR, 1.7 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, 2.5 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, 2.7 * i + j); + pc.setAxisValue(AINPUT_MOTION_AXIS_ORIENTATION, 3.5 * i + j); } } @@ -239,27 +241,27 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( for (size_t i = 0; i < pointerCount; i++) { SCOPED_TRACE(i); size_t offset = sampleIndex * pointerCount + i; - EXPECT_EQ(samplePointerCoords[offset].x, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_X), motionEvent->getHistoricalRawX(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].y, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_Y), motionEvent->getHistoricalRawY(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].x + xOffset, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_X) + xOffset, motionEvent->getHistoricalX(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].y + yOffset, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_Y) + yOffset, motionEvent->getHistoricalY(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].pressure, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_PRESSURE), motionEvent->getHistoricalPressure(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].size, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_SIZE), motionEvent->getHistoricalSize(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].touchMajor, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR), motionEvent->getHistoricalTouchMajor(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].touchMinor, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR), motionEvent->getHistoricalTouchMinor(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].toolMajor, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR), motionEvent->getHistoricalToolMajor(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].toolMinor, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR), motionEvent->getHistoricalToolMinor(i, sampleIndex)); - EXPECT_EQ(samplePointerCoords[offset].orientation, + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION), motionEvent->getHistoricalOrientation(i, sampleIndex)); } } @@ -269,17 +271,28 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( 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)); - EXPECT_EQ(samplePointerCoords[offset].touchMajor, motionEvent->getTouchMajor(i)); - EXPECT_EQ(samplePointerCoords[offset].touchMinor, motionEvent->getTouchMinor(i)); - EXPECT_EQ(samplePointerCoords[offset].toolMajor, motionEvent->getToolMajor(i)); - EXPECT_EQ(samplePointerCoords[offset].toolMinor, motionEvent->getToolMinor(i)); - EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_X), + motionEvent->getRawX(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_Y), + motionEvent->getRawY(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_X) + xOffset, + motionEvent->getX(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_Y) + yOffset, + motionEvent->getY(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_PRESSURE), + motionEvent->getPressure(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_SIZE), + motionEvent->getSize(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR), + motionEvent->getTouchMajor(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR), + motionEvent->getTouchMinor(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR), + motionEvent->getToolMajor(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR), + motionEvent->getToolMinor(i)); + EXPECT_EQ(samplePointerCoords[offset].getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION), + motionEvent->getOrientation(i)); } status = mConsumer->sendFinishedSignal(false); @@ -328,7 +341,8 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr const size_t pointerCount = 1; int32_t pointerIds[pointerCount] = { 0 }; - PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + PointerCoords pointerCoords[pointerCount]; + pointerCoords[0].clear(); status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); diff --git a/native/android/input.cpp b/native/android/input.cpp index a96240c..ed26667 100644 --- a/native/android/input.cpp +++ b/native/android/input.cpp @@ -172,6 +172,11 @@ float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointe return static_cast<const MotionEvent*>(motion_event)->getOrientation(pointer_index); } +float AMotionEvent_getAxisValue(const AInputEvent* motion_event, + int32_t axis, size_t pointer_index) { + return static_cast<const MotionEvent*>(motion_event)->getAxisValue(axis, pointer_index); +} + size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event) { return static_cast<const MotionEvent*>(motion_event)->getHistorySize(); } @@ -248,6 +253,12 @@ float AMotionEvent_getHistoricalOrientation(AInputEvent* motion_event, size_t po pointer_index, history_index); } +float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event, + int32_t axis, size_t pointer_index, size_t history_index) { + return static_cast<const MotionEvent*>(motion_event)->getHistoricalAxisValue( + axis, pointer_index, history_index); +} + void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper, int ident, ALooper_callbackFunc callback, void* data) { diff --git a/native/include/android/input.h b/native/include/android/input.h index bad363d..0ffb8b5 100644 --- a/native/include/android/input.h +++ b/native/include/android/input.h @@ -363,23 +363,40 @@ enum { }; /* + * Constants that identify each individual axis of a motion event. + */ +enum { + AINPUT_MOTION_AXIS_X = 0, + AINPUT_MOTION_AXIS_Y = 1, + AINPUT_MOTION_AXIS_PRESSURE = 2, + AINPUT_MOTION_AXIS_SIZE = 3, + AINPUT_MOTION_AXIS_TOUCH_MAJOR = 4, + AINPUT_MOTION_AXIS_TOUCH_MINOR = 5, + AINPUT_MOTION_AXIS_TOOL_MAJOR = 6, + AINPUT_MOTION_AXIS_TOOL_MINOR = 7, + AINPUT_MOTION_AXIS_ORIENTATION = 8, +}; + +/* * Constants used to retrieve information about the range of motion for a particular * coordinate of a motion event. * * Refer to the documentation on android.view.InputDevice for more details about input sources * and their correct interpretation. + * + * DEPRECATION NOTICE: These constants are deprecated. Use AINPUT_MOTION_AXIS_* constants instead. */ enum { - AINPUT_MOTION_RANGE_X = 0, - AINPUT_MOTION_RANGE_Y = 1, - AINPUT_MOTION_RANGE_PRESSURE = 2, - AINPUT_MOTION_RANGE_SIZE = 3, - AINPUT_MOTION_RANGE_TOUCH_MAJOR = 4, - AINPUT_MOTION_RANGE_TOUCH_MINOR = 5, - AINPUT_MOTION_RANGE_TOOL_MAJOR = 6, - AINPUT_MOTION_RANGE_TOOL_MINOR = 7, - AINPUT_MOTION_RANGE_ORIENTATION = 8, -}; + AINPUT_MOTION_RANGE_X = AINPUT_MOTION_AXIS_X, + AINPUT_MOTION_RANGE_Y = AINPUT_MOTION_AXIS_Y, + AINPUT_MOTION_RANGE_PRESSURE = AINPUT_MOTION_AXIS_PRESSURE, + AINPUT_MOTION_RANGE_SIZE = AINPUT_MOTION_AXIS_SIZE, + AINPUT_MOTION_RANGE_TOUCH_MAJOR = AINPUT_MOTION_AXIS_TOUCH_MAJOR, + AINPUT_MOTION_RANGE_TOUCH_MINOR = AINPUT_MOTION_AXIS_TOUCH_MINOR, + AINPUT_MOTION_RANGE_TOOL_MAJOR = AINPUT_MOTION_AXIS_TOOL_MAJOR, + AINPUT_MOTION_RANGE_TOOL_MINOR = AINPUT_MOTION_AXIS_TOOL_MINOR, + AINPUT_MOTION_RANGE_ORIENTATION = AINPUT_MOTION_AXIS_ORIENTATION, +} __attribute__ ((deprecated)); /* @@ -526,7 +543,7 @@ float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index); /* Get the current pressure of this event for the given pointer index. * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), - * however values higher than 1 may be generated depending on the calibration of + * although values higher than 1 may be generated depending on the calibration of * the input device. */ float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index); @@ -568,6 +585,10 @@ float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_ * (finger pointing fully right). */ float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index); +/* Get the value of the request axis for the given pointer index. */ +float AMotionEvent_getAxisValue(const AInputEvent* motion_event, + int32_t axis, size_t pointer_index); + /* Get the number of historical points in this event. These are movements that * have occurred between this event and the previous event. This only applies * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0. @@ -614,7 +635,7 @@ float AMotionEvent_getHistoricalY(AInputEvent* motion_event, size_t pointer_inde /* Get the historical pressure of this event for the given pointer index that * occurred between this event and the previous motion event. * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), - * however values higher than 1 may be generated depending on the calibration of + * although values higher than 1 may be generated depending on the calibration of * the input device. */ float AMotionEvent_getHistoricalPressure(AInputEvent* motion_event, size_t pointer_index, size_t history_index); @@ -669,6 +690,11 @@ float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_ float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index, size_t history_index); +/* Get the historical value of the request axis for the given pointer index + * that occurred between this event and the previous motion event. */ +float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event, + int32_t axis, size_t pointer_index, size_t history_index); + /* * Input queue diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index cbfdd75..466a9b3 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -482,8 +482,10 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplication != NULL) { - int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x); - int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y); + int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0]. + getAxisValue(AINPUT_MOTION_AXIS_X)); + int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0]. + getAxisValue(AINPUT_MOTION_AXIS_Y)); const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y); if (touchedWindow && touchedWindow->inputWindowHandle != NULL @@ -888,11 +890,15 @@ void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const M "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " "orientation=%f", i, entry->pointerIds[i], - sample->pointerCoords[i].x, sample->pointerCoords[i].y, - sample->pointerCoords[i].pressure, sample->pointerCoords[i].size, - sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor, - sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor, - sample->pointerCoords[i].orientation); + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_X), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_Y), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_PRESSURE), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_SIZE), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR), + sample->pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION)); } // Keep in mind that due to batching, it is possible for the number of samples actually @@ -1188,8 +1194,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, /* Case 1: New splittable pointer going down. */ int32_t pointerIndex = getMotionEventActionPointerIndex(action); - int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x); - int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y); + int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex]. + getAxisValue(AINPUT_MOTION_AXIS_X)); + int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex]. + getAxisValue(AINPUT_MOTION_AXIS_Y)); const InputWindow* newTouchedWindow = NULL; const InputWindow* topErrorWindow = NULL; @@ -2275,11 +2283,16 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, " "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " "orientation=%f", - i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y, - pointerCoords[i].pressure, pointerCoords[i].size, - pointerCoords[i].touchMajor, pointerCoords[i].touchMinor, - pointerCoords[i].toolMajor, pointerCoords[i].toolMinor, - pointerCoords[i].orientation); + i, pointerIds[i], + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_X), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_Y), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_PRESSURE), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_SIZE), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR), + pointerCoords[i].getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION)); } #endif if (! validateMotionEvent(action, pointerCount, pointerIds)) { diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 05f40ba..577da01 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -1285,24 +1285,23 @@ void CursorInputMapper::sync(nsecs_t when) { } } + pointerCoords.clear(); + if (mPointerController != NULL) { mPointerController->move(deltaX, deltaY); if (downChanged) { mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0); } - mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y); + float x, y; + mPointerController->getPosition(&x, &y); + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, x); + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, y); } else { - pointerCoords.x = deltaX; - pointerCoords.y = deltaY; + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, deltaX); + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, deltaY); } - pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f; - pointerCoords.size = 0; - pointerCoords.touchMajor = 0; - pointerCoords.touchMinor = 0; - pointerCoords.toolMajor = 0; - pointerCoords.toolMinor = 0; - pointerCoords.orientation = 0; + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f); } // release lock int32_t metaState = mContext->getGlobalMetaState(); @@ -2686,15 +2685,16 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, // Write output coords. PointerCoords& out = pointerCoords[outIndex]; - out.x = x; - out.y = y; - out.pressure = pressure; - out.size = size; - out.touchMajor = touchMajor; - out.touchMinor = touchMinor; - out.toolMajor = toolMajor; - out.toolMinor = toolMinor; - out.orientation = orientation; + out.clear(); + out.setAxisValue(AINPUT_MOTION_AXIS_X, x); + out.setAxisValue(AINPUT_MOTION_AXIS_Y, y); + out.setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, pressure); + out.setAxisValue(AINPUT_MOTION_AXIS_SIZE, size); + out.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR, touchMajor); + out.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR, touchMinor); + out.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, toolMajor); + out.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR, toolMinor); + out.setAxisValue(AINPUT_MOTION_AXIS_ORIENTATION, orientation); pointerIds[outIndex] = int32_t(id); @@ -2706,14 +2706,17 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, // Check edge flags by looking only at the first pointer since the flags are // global to the event. if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) { - if (pointerCoords[0].x <= 0) { + float x = pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X); + float y = pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y); + + if (x <= 0) { motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT; - } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) { + } else if (x >= mLocked.orientedSurfaceWidth) { motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT; } - if (pointerCoords[0].y <= 0) { + if (y <= 0) { motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP; - } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) { + } else if (y >= mLocked.orientedSurfaceHeight) { motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM; } } @@ -3853,15 +3856,9 @@ void JoystickInputMapper::sync(nsecs_t when) { if (motionAxisChanged) { PointerCoords pointerCoords; - pointerCoords.x = mAxes.x.value; - pointerCoords.y = mAxes.y.value; - pointerCoords.touchMajor = 0; - pointerCoords.touchMinor = 0; - pointerCoords.toolMajor = 0; - pointerCoords.toolMinor = 0; - pointerCoords.pressure = 0; - pointerCoords.size = 0; - pointerCoords.orientation = 0; + pointerCoords.clear(); + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, mAxes.x.value); + pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, mAxes.y.value); int32_t pointerId = 0; getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0, diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 8ec1fd4..34d613a 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -1473,15 +1473,15 @@ protected: float x, float y, float pressure, float size, float touchMajor, float touchMinor, float toolMajor, float toolMinor, float orientation) { - ASSERT_NEAR(x, coords.x, 1); - ASSERT_NEAR(y, coords.y, 1); - ASSERT_NEAR(pressure, coords.pressure, EPSILON); - ASSERT_NEAR(size, coords.size, EPSILON); - ASSERT_NEAR(touchMajor, coords.touchMajor, 1); - ASSERT_NEAR(touchMinor, coords.touchMinor, 1); - ASSERT_NEAR(toolMajor, coords.toolMajor, 1); - ASSERT_NEAR(toolMinor, coords.toolMinor, 1); - ASSERT_NEAR(orientation, coords.orientation, EPSILON); + ASSERT_NEAR(x, coords.getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(y, coords.getAxisValue(AINPUT_MOTION_AXIS_Y), 1); + ASSERT_NEAR(pressure, coords.getAxisValue(AINPUT_MOTION_AXIS_PRESSURE), EPSILON); + ASSERT_NEAR(size, coords.getAxisValue(AINPUT_MOTION_AXIS_SIZE), EPSILON); + ASSERT_NEAR(touchMajor, coords.getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR), 1); + ASSERT_NEAR(touchMinor, coords.getAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR), 1); + ASSERT_NEAR(toolMajor, coords.getAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR), 1); + ASSERT_NEAR(toolMinor, coords.getAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR), 1); + ASSERT_NEAR(orientation, coords.getAxisValue(AINPUT_MOTION_AXIS_ORIENTATION), EPSILON); } }; @@ -2078,7 +2078,6 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); - ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); } @@ -2893,8 +2892,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotate processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(50, args.pointerCoords[0].x, 1); - ASSERT_NEAR(75, args.pointerCoords[0].y, 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2915,8 +2914,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(50, args.pointerCoords[0].x, 1); - ASSERT_NEAR(75, args.pointerCoords[0].y, 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2928,8 +2927,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(75, args.pointerCoords[0].x, 1); - ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1); + ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2941,8 +2940,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1); - ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1); + ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y), 1); processUp(mapper); processSync(mapper); @@ -2954,8 +2953,8 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args)); - ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1); - ASSERT_NEAR(50, args.pointerCoords[0].y, 1); + ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X), 1); + ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y), 1); processUp(mapper); processSync(mapper); diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 5b329bb..427af23 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -87,7 +87,6 @@ static struct { jfieldID mName; jfieldID mSources; jfieldID mKeyboardType; - jfieldID mMotionRanges; } gInputDeviceClassInfo; static struct { @@ -1221,9 +1220,6 @@ int register_android_server_InputManager(JNIEnv* env) { GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz, "mKeyboardType", "I"); - GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz, - "mMotionRanges", "[Landroid/view/InputDevice$MotionRange;"); - // Configuration FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration"); |