diff options
55 files changed, 3269 insertions, 1355 deletions
@@ -207458,22 +207458,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 1ce49d4..9a38459 100644 --- a/api/current.xml +++ b/api/current.xml @@ -76371,6 +76371,17 @@ <parameter name="offsetXY" type="int[]"> </parameter> </method> +<method name="getByteCount" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getConfig" return="android.graphics.Bitmap.Config" abstract="false" @@ -121174,6 +121185,17 @@ visibility="public" > </field> +<field name="WIFI_MODE_FULL_HIGH_PERF" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="WIFI_MODE_SCAN_ONLY" type="int" transient="false" @@ -210563,7 +210585,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="rangeType" type="int"> +<parameter name="axis" type="int"> </parameter> </method> <method name="getName" @@ -210653,7 +210675,7 @@ value="8" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210664,7 +210686,7 @@ value="2" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210675,7 +210697,7 @@ value="3" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210686,7 +210708,7 @@ value="6" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210697,7 +210719,7 @@ value="7" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210708,7 +210730,7 @@ value="4" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210719,7 +210741,7 @@ value="5" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210730,7 +210752,7 @@ value="0" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -210741,7 +210763,7 @@ value="1" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> @@ -211020,22 +211042,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" > @@ -211825,6 +211847,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" @@ -211998,6 +212031,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" @@ -212254,6 +212298,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" @@ -216510,6 +216567,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" @@ -216554,6 +216650,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" @@ -216991,6 +217119,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" @@ -217299,7 +217438,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" @@ -217312,7 +217451,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" @@ -217382,6 +217521,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" @@ -217608,6 +217760,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" @@ -217690,6 +217941,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" @@ -265799,7 +266112,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/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index fa61b71..6172aab 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -212,4 +212,13 @@ class KeyframeSet { // shouldn't reach here return mLastKeyframe.getValue(); } + + @Override + public String toString() { + String returnVal = " "; + for (int i = 0; i < mNumKeyframes; ++i) { + returnVal += mKeyframes.get(i).getValue() + " "; + } + return returnVal; + } } diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index d038cd6..b8a7cb2 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -394,4 +394,16 @@ public final class ObjectAnimator extends ValueAnimator { final ObjectAnimator anim = (ObjectAnimator) super.clone(); return anim; } + + @Override + public String toString() { + String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + + mTarget; + if (mValues != null) { + for (int i = 0; i < mValues.length; ++i) { + returnVal += "\n " + mValues[i].toString(); + } + } + return returnVal; + } } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 0c30aad..6f91fc0 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -578,6 +578,11 @@ public class PropertyValuesHolder implements Cloneable { return mAnimatedValue; } + @Override + public String toString() { + return mPropertyName + ": " + mKeyframeSet.toString(); + } + /** * Utility method to derive a setter/getter method name from a property name, where the * prefix is typically "set" or "get" and the first letter of the property name is diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 5a8a74a..2e44d6d 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -1207,4 +1207,15 @@ public class ValueAnimator extends Animator { sPendingAnimations.get().clear(); sDelayedAnims.get().clear(); } + + @Override + public String toString() { + String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode()); + if (mValues != null) { + for (int i = 0; i < mValues.length; ++i) { + returnVal += "\n " + mValues[i].toString(); + } + } + return returnVal; + } } diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index eccd7c9..29f8caf 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -148,7 +148,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { /** * Action periodically sent to a device administrator when the device password - * is expiring. + * is expiring. * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive @@ -266,8 +266,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver { /** * Called periodically when the password is about to expire or has expired. It will typically - * be called on device boot, once per day before the password expires and at the time when it - * expires. + * be called at these times: on device boot, once per day before the password expires, + * and at the time when the password expires. * * <p>If the password is not updated by the user, this method will continue to be called * once per day until the password is changed or the device admin disables password expiration. diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d71a7a3..440cb54 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -730,8 +730,10 @@ public class DevicePolicyManager { } /** - * Get the current password expiration timeout for the given admin or the aggregate - * of all admins if admin is null. + * Get the password expiration timeout for the given admin. The expiration timeout is the + * recurring expiration timeout provided in the call to + * {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the + * aggregate of all policy administrators if admin is null. * * @param admin The name of the admin component to check, or null to aggregate all admins. * @return The timeout for the given admin or the minimum of all timeouts @@ -749,7 +751,9 @@ public class DevicePolicyManager { /** * Get the current password expiration time for the given admin or an aggregate of - * all admins if admin is null. + * all admins if admin is null. If the password is expired, this will return the time since + * the password expired as a negative number. If admin is null, then a composite of all + * expiration timeouts is returned - which will be the minimum of all timeouts. * * @param admin The name of the admin component to check, or null to aggregate all admins. * @return The password expiration time, in ms. diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index ebc1882..2cb8a86 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -241,7 +241,7 @@ public class SyncManager implements OnAccountsUpdateListener { // don't use the intent to figure out if network is connected, just check // ConnectivityManager directly. - mDataConnectionIsConnected = isNetworkConnected(); + mDataConnectionIsConnected = readDataConnectionState(); if (mDataConnectionIsConnected) { if (!wasConnected) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -254,7 +254,7 @@ public class SyncManager implements OnAccountsUpdateListener { } }; - private boolean isNetworkConnected() { + private boolean readDataConnectionState() { NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo(); return (networkInfo != null) && networkInfo.isConnected(); } @@ -1429,7 +1429,7 @@ public class SyncManager implements OnAccountsUpdateListener { // to have the most recent value used. try { waitUntilReadyToRun(); - mDataConnectionIsConnected = isNetworkConnected(); + mDataConnectionIsConnected = readDataConnectionState(); mSyncManagerWakeLock.acquire(); // Always do this first so that we be sure that any periodic syncs that // are ready to run have been converted into pending syncs. This allows the 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/java/android/view/View.java b/core/java/android/view/View.java index b982c7b..48451ba 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6061,9 +6061,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (top != mTop) { updateMatrix(); if (mMatrixIsIdentity) { - final ViewParent p = mParent; - if (p != null && mAttachInfo != null) { - final Rect r = mAttachInfo.mTmpInvalRect; + if (mAttachInfo != null) { int minTop; int yLoc; if (top < mTop) { @@ -6073,8 +6071,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility minTop = mTop; yLoc = 0; } - r.set(0, yLoc, mRight - mLeft, mBottom - minTop); - p.invalidateChild(this, r); + invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); } } else { // Double-invalidation is necessary to capture view's old and new areas @@ -6131,17 +6128,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (bottom != mBottom) { updateMatrix(); if (mMatrixIsIdentity) { - final ViewParent p = mParent; - if (p != null && mAttachInfo != null) { - final Rect r = mAttachInfo.mTmpInvalRect; + if (mAttachInfo != null) { int maxBottom; if (bottom < mBottom) { maxBottom = mBottom; } else { maxBottom = bottom; } - r.set(0, 0, mRight - mLeft, maxBottom - mTop); - p.invalidateChild(this, r); + invalidate(0, 0, mRight - mLeft, maxBottom - mTop); } } else { // Double-invalidation is necessary to capture view's old and new areas @@ -6189,9 +6183,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (left != mLeft) { updateMatrix(); if (mMatrixIsIdentity) { - final ViewParent p = mParent; - if (p != null && mAttachInfo != null) { - final Rect r = mAttachInfo.mTmpInvalRect; + if (mAttachInfo != null) { int minLeft; int xLoc; if (left < mLeft) { @@ -6201,8 +6193,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility minLeft = mLeft; xLoc = 0; } - r.set(xLoc, 0, mRight - minLeft, mBottom - mTop); - p.invalidateChild(this, r); + invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); } } else { // Double-invalidation is necessary to capture view's old and new areas @@ -6250,17 +6241,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (right != mRight) { updateMatrix(); if (mMatrixIsIdentity) { - final ViewParent p = mParent; - if (p != null && mAttachInfo != null) { - final Rect r = mAttachInfo.mTmpInvalRect; + if (mAttachInfo != null) { int maxRight; if (right < mRight) { maxRight = mRight; } else { maxRight = right; } - r.set(0, 0, maxRight - mLeft, mBottom - mTop); - p.invalidateChild(this, r); + invalidate(0, 0, maxRight - mLeft, mBottom - mTop); } } else { // Double-invalidation is necessary to capture view's old and new areas diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 8e09986..fc1240f 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -21,6 +21,8 @@ import android.content.ComponentCallbacks; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.net.ParseException; import android.net.Uri; @@ -933,7 +935,19 @@ class BrowserFrame extends Handler { if (androidResource != null) { return new WebResourceResponse(null, null, androidResource); } - return mCallbackProxy.shouldInterceptRequest(url); + WebResourceResponse response = mCallbackProxy.shouldInterceptRequest(url); + if (response == null && "browser:incognito".equals(url)) { + try { + Resources res = mContext.getResources(); + InputStream ins = res.openRawResource( + com.android.internal.R.raw.incognito_mode_start_page); + response = new WebResourceResponse("text/html", "utf8", ins); + } catch (NotFoundException ex) { + // This shouldn't happen, but try and gracefully handle it jic + Log.w(LOGTAG, "Failed opening raw.incognito_mode_start_page", ex); + } + } + return response; } /** diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java index 04062fe..3ce0730 100644 --- a/core/java/android/webkit/CacheManager.java +++ b/core/java/android/webkit/CacheManager.java @@ -198,8 +198,6 @@ public final class CacheManager { mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging"); if (!mBaseDir.exists()) { mBaseDir.mkdirs(); - } else { - // TODO: Should we clear out old files? } return; } @@ -605,11 +603,12 @@ public final class CacheManager { * @return Whether the removal succeeded. */ static boolean removeAllCacheFiles() { - assert !JniUtil.useChromiumHttpStack(); - // Note, this is called before init() when the database is // created or upgraded. if (mBaseDir == null) { + // This method should not be called before init() when using the + // chrome http stack + assert !JniUtil.useChromiumHttpStack(); // Init() has not been called yet, so just flag that // we need to clear the cache when init() is called. mClearCacheOnInit = true; diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 0bf0eab..71d6080 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -174,6 +174,7 @@ public class WebSettings { private boolean mBlockNetworkImage = false; private boolean mBlockNetworkLoads; private boolean mJavaScriptEnabled = false; + private boolean mShowVisualIndicator = false; private PluginState mPluginState = PluginState.OFF; private boolean mJavaScriptCanOpenWindowsAutomatically = false; private boolean mUseDoubleTree = false; @@ -1191,6 +1192,26 @@ public class WebSettings { } /** + * Tell the WebView to show the visual indicator + * @param flag True if the WebView should show the visual indicator + * @hide + */ + public synchronized void setShowVisualIndicator(boolean flag) { + if (mShowVisualIndicator != flag) { + mShowVisualIndicator = flag; + postSync(); + } + } + + /** + * @return True if the WebView is showing the visual indicator + * @hide + */ + public synchronized boolean getShowVisualIndicator() { + return mShowVisualIndicator; + } + + /** * Tell the WebView to enable plugins. * @param flag True if the WebView should load plugins. * @deprecated This method has been deprecated in favor of diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 7d8289a..69e658f 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2089,7 +2089,7 @@ public class WebView extends AbsoluteLayout public void clearView() { mContentWidth = 0; mContentHeight = 0; - setBaseLayer(0, null); + setBaseLayer(0, null, false); mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT); } @@ -3996,14 +3996,14 @@ public class WebView extends AbsoluteLayout } } - void setBaseLayer(int layer, Rect invalRect) { + void setBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator) { if (mNativeClass == 0) return; if (invalRect == null) { Rect rect = new Rect(0, 0, mContentWidth, mContentHeight); - nativeSetBaseLayer(layer, rect); + nativeSetBaseLayer(layer, rect, showVisualIndciator); } else { - nativeSetBaseLayer(layer, invalRect); + nativeSetBaseLayer(layer, invalRect, showVisualIndciator); } } @@ -7205,7 +7205,8 @@ public class WebView extends AbsoluteLayout case NEW_PICTURE_MSG_ID: { // called for new content final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj; - setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds()); + setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds(), + getSettings().getShowVisualIndicator()); final Point viewSize = draw.mViewSize; WebViewCore.ViewState viewState = draw.mViewState; boolean isPictureAfterFirstLayout = viewState != null; @@ -8337,7 +8338,8 @@ public class WebView extends AbsoluteLayout private native void nativeSetFindIsEmpty(); private native void nativeSetFindIsUp(boolean isUp); private native void nativeSetHeightCanMeasure(boolean measure); - private native void nativeSetBaseLayer(int layer, Rect invalRect); + private native void nativeSetBaseLayer(int layer, Rect invalRect, + boolean showVisualIndciator); private native void nativeShowCursorTimed(); private native void nativeReplaceBaseContent(int content); private native void nativeCopyBaseContentToPicture(Picture pict); diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 3bdba62..27610b9 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -92,6 +92,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe static final boolean DEBUG = false; static final String TAG = "AutoCompleteTextView"; + static final int EXPAND_MAX = 3; + private CharSequence mHintText; private TextView mHintView; private int mHintResource; @@ -1057,8 +1059,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe if (!isPopupShowing()) { // Make sure the list does not obscure the IME when shown for the first time. mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED); + mPopup.setListItemExpandMax(EXPAND_MAX); } mPopup.show(); + mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS); } /** diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 560fc68..5642877 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -65,6 +65,7 @@ public class ListPopupWindow { private boolean mDropDownAlwaysVisible = false; private boolean mForceIgnoreOutsideTouch = false; + int mListItemExpandMaximum = Integer.MAX_VALUE; private View mPromptView; private int mPromptPosition = POSITION_PROMPT_ABOVE; @@ -519,6 +520,7 @@ public class ListPopupWindow { int heightSpec = 0; boolean noInputMethod = isInputMethodNotNeeded(); + mPopup.setAllowScrollingAnchorParent(!noInputMethod); if (mPopup.isShowing()) { if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { @@ -775,6 +777,16 @@ public class ListPopupWindow { } /** + * The maximum number of list items that can be visible and still have + * the list expand when touched. + * + * @param max Max number of items that can be visible and still allow the list to expand. + */ + void setListItemExpandMax(int max) { + mListItemExpandMaximum = max; + } + + /** * Filter key down events. By forwarding key down events to this function, * views using non-modal ListPopupWindow can have it handle key selection of items. * @@ -1210,8 +1222,11 @@ public class ListPopupWindow { private class ResizePopupRunnable implements Runnable { public void run() { - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); - show(); + if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() && + mDropDownList.getChildCount() <= mListItemExpandMaximum) { + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); + show(); + } } } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 439e0ca..53932af 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -90,6 +90,7 @@ public class PopupWindow { private int mSplitTouchEnabled = -1; private boolean mLayoutInScreen; private boolean mClipToScreen; + private boolean mAllowScrollingAnchorParent = true; private OnTouchListener mTouchInterceptor; @@ -592,6 +593,16 @@ public class PopupWindow { mClipToScreen = enabled; setClippingEnabled(!enabled); } + + /** + * Allow PopupWindow to scroll the anchor's parent to provide more room + * for the popup. Enabled by default. + * + * @param enabled True to scroll the anchor's parent when more room is desired by the popup. + */ + void setAllowScrollingAnchorParent(boolean enabled) { + mAllowScrollingAnchorParent = enabled; + } /** * <p>Indicates whether the popup window supports splitting touches.</p> @@ -1045,7 +1056,8 @@ public class PopupWindow { anchor.getWindowVisibleDisplayFrame(displayFrame); final View root = anchor.getRootView(); - if (p.y + mPopupHeight > displayFrame.bottom || p.x + mPopupWidth - root.getWidth() > 0) { + if (mAllowScrollingAnchorParent && (p.y + mPopupHeight > displayFrame.bottom || + p.x + mPopupWidth - root.getWidth() > 0)) { // if the drop down disappears at the bottom of the screen. we try to // scroll a parent scrollview or move the drop down back up on top of // the edit box diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 6a09d35..e6cf31e 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -1207,6 +1207,7 @@ public class StackView extends AdapterViewAnimator { void invalidateGlobalRegion(View v, Rect r) { // We need to make a new rect here, so as not to modify the one passed globalInvalidateRect.set(r); + globalInvalidateRect.union(0, 0, getWidth(), getHeight()); View p = v; if (!(v.getParent() != null && v.getParent() instanceof View)) return; @@ -1223,8 +1224,9 @@ public class StackView extends AdapterViewAnimator { firstPass = false; p = (View) p.getParent(); parentRect.set(p.getScrollX(), p.getScrollY(), - p.getWidth() + p.getScrollX(), p.getHeight() + p.getScrollY()); - + p.getWidth() + p.getScrollX(), p.getHeight() + p.getScrollY()); + p.invalidate(globalInvalidateRect.left, globalInvalidateRect.top, + globalInvalidateRect.right, globalInvalidateRect.bottom); } p.invalidate(globalInvalidateRect.left, globalInvalidateRect.top, 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/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..b9435b6 --- /dev/null +++ b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png Binary files differnew file mode 100644 index 0000000..477d820 --- /dev/null +++ b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png diff --git a/core/res/res/raw-es/incognito_mode_start_page.html b/core/res/res/raw-es/incognito_mode_start_page.html new file mode 100644 index 0000000..43fd37f --- /dev/null +++ b/core/res/res/raw-es/incognito_mode_start_page.html @@ -0,0 +1,26 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> + <title>Nueva ventana de incógnito</title> + </head> + <body> + <p><strong>Has entrado en el modo "Navegar de incógnito"</strong>. Las páginas + que consultes a través de esta ventana no quedarán registradas en el historial del navegador + ni en el historial de búsquedas, y tampoco dejarán otros rastros en el equipo (como cookies) + una vez cerrada. Aunque sà quedarán almacenados los archivos que descargues y los marcadores + que guardes durante la sesión.</p> + + <p><strong>La función "Navegar de incógnito" no afecta al comportamiento de + otros usuarios, servidores o programas. Atención con:</strong></p> + + <ul> + <li>sitios web que recopilan o comparten información personal,</li> + <li>proveedores de servicios de Internet o trabajadores de estas empresas que + supervisan las páginas que visita el usuario,</li> + <li>software malicioso que realiza un seguimiento de las teclas que pulsa el usuario a + cambio de unos emoticones gratuitos,</li> + <li>el seguimiento por parte de detectives privados,</li> + <li>personas merodeando cerca de tu equipo.</li> + </ul> + </body> +</html> diff --git a/core/res/res/raw/incognito_mode_start_page.html b/core/res/res/raw/incognito_mode_start_page.html new file mode 100644 index 0000000..5d7a3fb --- /dev/null +++ b/core/res/res/raw/incognito_mode_start_page.html @@ -0,0 +1,24 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> + <title>New incognito window</title> + </head> + <body> + <p><strong>You've gone incognito</strong>. Pages you view in this window + won't appear in your browser history or search history, and they won't + leave other traces, like cookies, on your device after you close the + incognito window. Any files you download or bookmarks you create will be + preserved, however.</p> + + <p><strong>Going incognito doesn't affect the behavior of other people, + servers, or software. Be wary of:</strong></p> + + <ul> + <li>Websites that collect or share information about you</li> + <li>Internet service providers or employers that track the pages you visit</li> + <li>Malicious software that tracks your keystrokes in exchange for free smileys</li> + <li>Surveillance by secret agents</li> + <li>People standing behind you</li> + </ul> + </body> +</html> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d09210e..361bb6c 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1413,10 +1413,10 @@ to be used while policy is enabled. Only the first device admin sets the effective global proxy.</string> <!-- Title of policy access to enforce password expiration [CHAR LIMIT=30]--> - <string name="policylab_expirePassword">Set password expiration</string> + <string name="policylab_expirePassword">Set lock-screen password expiration</string> <!-- Description of policy access to enforce password expiration [CHAR LIMIT=110]--> - <string name="policydesc_expirePassword">Control how long before lockscreen password needs to be - changed</string> + <string name="policydesc_expirePassword">Control how frequently the lock-screen password must be + changed</string> <!-- Title of policy access to require encrypted storage [CHAR LIMIT=30]--> <string name="policylab_encryptedStorage">Set storage encryption</string> <!-- Description of policy access to require encrypted storage [CHAR LIMIT=110]--> diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index b2f4379..12dc93c 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -19,7 +19,6 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; import android.util.DisplayMetrics; - import java.io.OutputStream; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -342,7 +341,7 @@ public final class Bitmap implements Parcelable { } long bufferSize = (long)elements << shift; - long pixelSize = (long)getRowBytes() * getHeight(); + long pixelSize = getByteCount(); if (bufferSize < pixelSize) { throw new RuntimeException("Buffer not large enough for pixels"); @@ -378,7 +377,7 @@ public final class Bitmap implements Parcelable { } long bufferBytes = (long)elements << shift; - long bitmapBytes = (long)getRowBytes() * getHeight(); + long bitmapBytes = getByteCount(); if (bufferBytes < bitmapBytes) { throw new RuntimeException("Buffer not large enough for pixels"); @@ -822,6 +821,14 @@ public final class Bitmap implements Parcelable { } /** + * Returns the number of bytes used to store this bitmap's pixels. + */ + public final int getByteCount() { + // int result permits bitmaps up to 46,340 x 46,340 + return getRowBytes() * getHeight(); + } + + /** * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. */ diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index d8a7f9d..0a23bae 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1254,9 +1254,7 @@ public class Paint { * @param text The text to measure * @param index The offset into text to begin measuring at * @param count The number of maximum number of entries to measure. If count - * is negative, then the characters before index are measured - * in reverse order. This allows for measuring the end of - * string. + * is negative, then the characters are measured in reverse order. * @param maxWidth The maximum width to accumulate. * @param measuredWidth Optional. If not null, returns the actual width * measured. diff --git a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java index 6734bb7..685a998 100644 --- a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java +++ b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java @@ -16,8 +16,6 @@ package android.graphics; -import android.graphics.Bitmap; -import android.graphics.Color; import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; @@ -42,6 +40,10 @@ public class BitmapTest extends TestCase { assertEquals("rowbytes", 200, bm2.getRowBytes()); assertEquals("rowbytes", 200, bm3.getRowBytes()); + assertEquals("byteCount", 80000, bm1.getByteCount()); + assertEquals("byteCount", 40000, bm2.getByteCount()); + assertEquals("byteCount", 40000, bm3.getByteCount()); + assertEquals("height", 200, bm1.getHeight()); assertEquals("height", 200, bm2.getHeight()); assertEquals("height", 200, bm3.getHeight()); 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/rs/java/ModelViewer/AndroidManifest.xml b/libs/rs/java/ModelViewer/AndroidManifest.xml index 959fe53..e5e449b 100644 --- a/libs/rs/java/ModelViewer/AndroidManifest.xml +++ b/libs/rs/java/ModelViewer/AndroidManifest.xml @@ -3,14 +3,19 @@ package="com.android.modelviewer"> <application android:label="ModelViewer"> <activity android:name="SimpleModel" - android:label="SimpleModel" - android:screenOrientation="portrait" - android:theme="@android:style/Theme.Black.NoTitleBar"> + android:label="SimpleModel"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name="A3DSelector" + android:label="A3DSelector" + android:hardwareAccelerated="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> <activity android:name="SceneGraph" android:label="SceneGraph" android:theme="@android:style/Theme.Black.NoTitleBar"> diff --git a/libs/rs/java/ModelViewer/res/menu/loader_menu.xml b/libs/rs/java/ModelViewer/res/menu/loader_menu.xml new file mode 100644 index 0000000..3c34023 --- /dev/null +++ b/libs/rs/java/ModelViewer/res/menu/loader_menu.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +--> + +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/load_model" + android:title="@string/load_model" /> + <item android:id="@+id/display_options" + android:title="@string/display_options" /> +</menu> diff --git a/libs/rs/java/ModelViewer/res/values/strings.xml b/libs/rs/java/ModelViewer/res/values/strings.xml new file mode 100644 index 0000000..8e1673f --- /dev/null +++ b/libs/rs/java/ModelViewer/res/values/strings.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <skip /> + <string name="load_model">Load Model</string> + <string name="display_options">Display Options</string> +</resources> diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/A3DSelector.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/A3DSelector.java new file mode 100644 index 0000000..0e2004f --- /dev/null +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/A3DSelector.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.modelviewer; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.List; + +import android.app.ListActivity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +/** + * A list view where the last item the user clicked is placed in + * the "activated" state, causing its background to highlight. + */ +public class A3DSelector extends ListActivity { + + File[] mCurrentSubList; + File mCurrentFile; + + class A3DFilter implements FileFilter { + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + return file.getName().endsWith(".a3d"); + } + } + + private void populateList(File file) { + + mCurrentFile = file; + setTitle(mCurrentFile.getAbsolutePath() + "/*.a3d"); + List<String> names = new ArrayList<String>(); + names.add(".."); + + mCurrentSubList = mCurrentFile.listFiles(new A3DFilter()); + + if (mCurrentSubList != null) { + for (int i = 0; i < mCurrentSubList.length; i ++) { + String fileName = mCurrentSubList[i].getName(); + if (mCurrentSubList[i].isDirectory()) { + fileName = "/" + fileName; + } + names.add(fileName); + } + } + + // Use the built-in layout for showing a list item with a single + // line of text whose background is changes when activated. + setListAdapter(new ArrayAdapter<String>(this, + android.R.layout.simple_list_item_activated_1, names)); + getListView().setTextFilterEnabled(true); + + // Tell the list view to show one checked/activated item at a time. + getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + populateList(new File("/sdcard/")); + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + if (position == 0) { + File parent = mCurrentFile.getParentFile(); + if (parent == null) { + return; + } + populateList(parent); + return; + } + + // the first thing in list is parent directory + File selectedFile = mCurrentSubList[position - 1]; + if (selectedFile.isDirectory()) { + populateList(selectedFile); + return; + } + + Intent resultIntent = new Intent(); + resultIntent.setData(Uri.fromFile(selectedFile)); + setResult(RESULT_OK, resultIntent); + finish(); + } + +} diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java index 9910970..01cb709 100644 --- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java @@ -21,6 +21,7 @@ import android.renderscript.RenderScript; import android.app.Activity; import android.content.res.Configuration; +import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -31,9 +32,11 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.MenuInflater; import android.view.Window; import android.widget.Button; import android.widget.ListView; +import android.net.Uri; import java.lang.Runtime; @@ -67,5 +70,45 @@ public class SimpleModel extends Activity { mView.pause(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.loader_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle item selection + switch (item.getItemId()) { + case R.id.load_model: + loadModel(); + return true; + case R.id.display_options: + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private static final int FIND_A3D_MODEL = 10; + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + if (requestCode == FIND_A3D_MODEL) { + Uri selectedImageUri = data.getData(); + Log.e("Selected Path: ", selectedImageUri.getPath()); + mView.loadA3DFile(selectedImageUri.getPath()); + } + } + } + + public void loadModel() { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_PICK); + intent.setClassName("com.android.modelviewer", + "com.android.modelviewer.A3DSelector"); + startActivityForResult(intent, FIND_A3D_MODEL); + } + } diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java index b18a327..63ef466 100644 --- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,24 +26,20 @@ import android.util.Log; public class SimpleModelRS { - private final int STATE_LAST_FOCUS = 1; - - int mWidth; - int mHeight; - int mRotation; - public SimpleModelRS() { } - public void init(RenderScriptGL rs, Resources res, int width, int height) { + public void init(RenderScriptGL rs, Resources res) { mRS = rs; mRes = res; - mWidth = width; - mHeight = height; - mRotation = 0; initRS(); } + public void surfaceChanged() { + mRS.getWidth(); + mRS.getHeight(); + } + private Resources mRes; private RenderScriptGL mRS; private Sampler mSampler; @@ -55,34 +51,23 @@ public class SimpleModelRS { private Allocation mGridImage; private Allocation mAllocPV; - private Mesh mMesh; - private Font mItalic; private Allocation mTextAlloc; + private ScriptField_MeshInfo mMeshes; private ScriptC_simplemodel mScript; - int mLastX; - int mLastY; - public void touchEvent(int x, int y) { - int dx = mLastX - x; - if (Math.abs(dx) > 50 || Math.abs(dx) < 3) { - dx = 0; - } - - mRotation -= dx; - if (mRotation > 360) { - mRotation -= 360; - } - if (mRotation < 0) { - mRotation += 360; - } + public void onActionDown(float x, float y) { + mScript.invoke_onActionDown(x, y); + } - mScript.set_gRotate((float)mRotation); + public void onActionScale(float scale) { + mScript.invoke_onActionScale(scale); + } - mLastX = x; - mLastY = y; + public void onActionMove(float x, float y) { + mScript.invoke_onActionMove(x, y); } private void initPFS() { @@ -130,12 +115,48 @@ public class SimpleModelRS { mScript.set_gTGrid(mGridImage); } - private void initTextAllocation() { - String allocString = "Displaying file: R.raw.robot"; + private void initTextAllocation(String fileName) { + String allocString = "Displaying file: " + fileName; mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT); mScript.set_gTextAlloc(mTextAlloc); } + private void initMeshes(FileA3D model) { + int numEntries = model.getIndexEntryCount(); + int numMeshes = 0; + for (int i = 0; i < numEntries; i ++) { + FileA3D.IndexEntry entry = model.getIndexEntry(i); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + numMeshes ++; + } + } + + if (numMeshes > 0) { + mMeshes = new ScriptField_MeshInfo(mRS, numMeshes); + + for (int i = 0; i < numEntries; i ++) { + FileA3D.IndexEntry entry = model.getIndexEntry(i); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + Mesh mesh = entry.getMesh(); + mMeshes.set_mMesh(i, mesh, false); + mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false); + } + } + mMeshes.copyAll(); + } else { + throw new RSRuntimeException("No valid meshes in file"); + } + + mScript.bind_gMeshes(mMeshes); + mScript.invoke_updateMeshInfo(); + } + + public void loadA3DFile(String path) { + FileA3D model = FileA3D.createFromFile(mRS, path); + initMeshes(model); + initTextAllocation(path); + } + private void initRS() { mScript = new ScriptC_simplemodel(mRS, mRes, R.raw.simplemodel); @@ -147,18 +168,12 @@ public class SimpleModelRS { loadImage(); FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); - FileA3D.IndexEntry entry = model.getIndexEntry(0); - if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { - Log.e("rs", "could not load model"); - } else { - mMesh = (Mesh)entry.getObject(); - mScript.set_gTestMesh(mMesh); - } + initMeshes(model); mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); mScript.set_gItalic(mItalic); - initTextAllocation(); + initTextAllocation("R.raw.robot"); mRS.bindRootScript(mScript); } diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java index 5c5956d..9ab0f22 100644 --- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,81 +16,129 @@ package com.android.modelviewer; -import java.io.Writer; -import java.util.ArrayList; -import java.util.concurrent.Semaphore; - import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScript; import android.renderscript.RenderScriptGL; import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.ScaleGestureDetector; +import android.util.Log; public class SimpleModelView extends RSSurfaceView { - public SimpleModelView(Context context) { - super(context); - //setFocusable(true); - } - private RenderScriptGL mRS; private SimpleModelRS mRender; + private ScaleGestureDetector mScaleDetector; - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); + private static final int INVALID_POINTER_ID = -1; + private int mActivePointerId = INVALID_POINTER_ID; + + public SimpleModelView(Context context) { + super(context); + ensureRenderScript(); + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + } + + private void ensureRenderScript() { if (mRS == null) { RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); sc.setDepth(16, 24); mRS = createRenderScriptGL(sc); - mRS.setSurface(holder, w, h); mRender = new SimpleModelRS(); - mRender.init(mRS, getResources(), w, h); + mRender.init(mRS, getResources()); } } @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + ensureRenderScript(); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + mRender.surfaceChanged(); + } + + @Override protected void onDetachedFromWindow() { + mRender = null; if (mRS != null) { mRS = null; destroyRenderScriptGL(); } } - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - // break point at here - // this method doesn't work when 'extends View' include 'extends ScrollView'. - return super.onKeyDown(keyCode, event); + public void loadA3DFile(String path) { + mRender.loadA3DFile(path); } - @Override - public boolean onTouchEvent(MotionEvent ev) - { - boolean ret = true; - int act = ev.getAction(); - if (act == ev.ACTION_UP) { - ret = false; + public boolean onTouchEvent(MotionEvent ev) { + mScaleDetector.onTouchEvent(ev); + + boolean ret = false; + float x = ev.getX(); + float y = ev.getY(); + + final int action = ev.getAction(); + + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(0); + ret = true; + break; + } + case MotionEvent.ACTION_MOVE: { + if (!mScaleDetector.isInProgress()) { + mRender.onActionMove(x, y); + } + mRender.onActionDown(x, y); + ret = true; + break; + } + + case MotionEvent.ACTION_UP: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_CANCEL: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_POINTER_UP: { + final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) + >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + x = ev.getX(newPointerIndex); + y = ev.getY(newPointerIndex); + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(newPointerIndex); + } + break; + } } - mRender.touchEvent((int)ev.getX(), (int)ev.getY()); return ret; } + + private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + @Override + public boolean onScale(ScaleGestureDetector detector) { + mRender.onActionScale(detector.getScaleFactor()); + return true; + } + } } diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs index 419de62..1034b85 100644 --- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2009 The Android Open Source Project +// Copyright (C) 2011 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,17 +22,112 @@ rs_program_vertex gPVBackground; rs_program_fragment gPFBackground; rs_allocation gTGrid; -rs_mesh gTestMesh; rs_program_store gPFSBackground; -float gRotate; - rs_font gItalic; rs_allocation gTextAlloc; +typedef struct MeshInfo { + rs_mesh mMesh; + int mNumIndexSets; + float3 bBoxMin; + float3 bBoxMax; +} MeshInfo_t; + +MeshInfo_t *gMeshes; + +static float3 gLookAt; + +static float gRotateX; +static float gRotateY; +static float gZoom; + +static float gLastX; +static float gLastY; + +void onActionDown(float x, float y) { + gLastX = x; + gLastY = y; +} + +void onActionScale(float scale) { + + gZoom *= 1.0f / scale; + gZoom = max(0.1f, min(gZoom, 500.0f)); +} + +void onActionMove(float x, float y) { + float dx = gLastX - x; + float dy = gLastY - y; + + if (fabs(dy) <= 2.0f) { + dy = 0.0f; + } + if (fabs(dx) <= 2.0f) { + dx = 0.0f; + } + + gRotateY -= dx; + if (gRotateY > 360) { + gRotateY -= 360; + } + if (gRotateY < 0) { + gRotateY += 360; + } + + gRotateX -= dy; + gRotateX = min(gRotateX, 80.0f); + gRotateX = max(gRotateX, -80.0f); + + gLastX = x; + gLastY = y; +} + void init() { - gRotate = 0.0f; + gRotateX = 0.0f; + gRotateY = 0.0f; + gZoom = 50.0f; + gLookAt = 0.0f; +} + +void updateMeshInfo() { + rs_allocation allMeshes = rsGetAllocation(gMeshes); + int size = rsAllocationGetDimX(allMeshes); + gLookAt = 0.0f; + float minX, minY, minZ, maxX, maxY, maxZ; + for (int i = 0; i < size; i++) { + MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); + rsgMeshComputeBoundingBox(info->mMesh, + &minX, &minY, &minZ, + &maxX, &maxY, &maxZ); + info->bBoxMin = (minX, minY, minZ); + info->bBoxMax = (maxX, maxY, maxZ); + gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f; + } + gLookAt = gLookAt / (float)size; +} + +static void renderAllMeshes() { + rs_allocation allMeshes = rsGetAllocation(gMeshes); + int size = rsAllocationGetDimX(allMeshes); + gLookAt = 0.0f; + float minX, minY, minZ, maxX, maxY, maxZ; + for (int i = 0; i < size; i++) { + MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); + rsgDrawMesh(info->mMesh); + } +} + +void drawDescription() { + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + + rsgBindFont(gItalic); + + rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); + rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom); } int root(int launchID) { @@ -43,7 +138,7 @@ int root(int launchID) { rsgBindProgramVertex(gPVBackground); rs_matrix4x4 proj; float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); rsgProgramVertexLoadProjectionMatrix(&proj); rsgBindProgramFragment(gPFBackground); @@ -52,20 +147,15 @@ int root(int launchID) { rs_matrix4x4 matrix; rsMatrixLoadIdentity(&matrix); - // Position our model on the screen - rsMatrixTranslate(&matrix, 0.0f, -0.3f, -10.0f); - rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f); - rsMatrixRotate(&matrix, 25.0f, 1.0f, 0.0f, 0.0f); - rsMatrixRotate(&matrix, gRotate, 0.0f, 1.0f, 0.0f); + // Position our models on the screen + rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom); + rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); rsgProgramVertexLoadModelMatrix(&matrix); - rsgDrawMesh(gTestMesh); - - rsgFontColor(0.3f, 0.3f, 0.3f, 1.0f); - rsgDrawText("Renderscript model test", 30, 695); + renderAllMeshes(); - rsgBindFont(gItalic); - rsgDrawText(gTextAlloc, 30, 730); + drawDescription(); return 10; } 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 a4d5f35..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(); @@ -2641,9 +2640,11 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, int32_t c2 = signExtendNybble(in.orientation & 0x0f); if (c1 != 0 || c2 != 0) { orientation = atan2f(c1, c2) * 0.5f; - float minorAxisScale = (16.0f - pythag(c1, c2)) / 16.0f; - toolMinor *= minorAxisScale; - touchMinor *= minorAxisScale; + float scale = 1.0f + pythag(c1, c2) / 16.0f; + touchMajor *= scale; + touchMinor /= scale; + toolMajor *= scale; + toolMinor /= scale; } else { orientation = 0; } @@ -2684,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); @@ -2704,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; } } @@ -3851,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/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index b2d534b..df2cd1b 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -79,9 +79,9 @@ import java.util.Set; * Implementation of the device policy APIs. */ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { - private static final int REQUEST_EXPIRE_PASSWORD = 5571; + private static final String TAG = "DevicePolicyManagerService"; - static final String TAG = "DevicePolicyManagerService"; + private static final int REQUEST_EXPIRE_PASSWORD = 5571; private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms 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"); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fde8e67..0f7d639 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -142,7 +142,8 @@ void Layer::onRemoved() sp<LayerBaseClient::Surface> Layer::createSurface() const { - return mSurface; + sp<Surface> sur(new SurfaceLayer(mFlinger, const_cast<Layer *>(this))); + return sur; } status_t Layer::ditch() @@ -152,9 +153,6 @@ status_t Layer::ditch() // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); - // Free our own reference to ISurface - mSurface.clear(); - Mutex::Autolock _l(mLock); mWidth = mHeight = 0; return NO_ERROR; @@ -202,7 +200,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); mNeedsDithering = layerRedsize > displayRedSize; - mSurface = new SurfaceLayer(mFlinger, this); return NO_ERROR; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d9a8be3..2b38414 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -213,7 +213,6 @@ private: ClientRef mUserClientRef; // constants - sp<Surface> mSurface; PixelFormat mFormat; const GLExtensions& mGLExtensions; bool mNeedsBlending; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 86057f8..6025ed4 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -540,7 +540,9 @@ int32_t LayerBaseClient::sIdentity = 1; LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client) - : LayerBase(flinger, display), mClientRef(client), + : LayerBase(flinger, display), + mHasSurface(false), + mClientRef(client), mIdentity(uint32_t(android_atomic_inc(&sIdentity))) { } @@ -557,12 +559,13 @@ sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() { sp<Surface> s; Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = createSurface(); - mClientSurface = s; - mClientSurfaceBinder = s->asBinder(); - } + + LOG_ALWAYS_FATAL_IF(mHasSurface, + "LayerBaseClient::getSurface() has already been called"); + + mHasSurface = true; + s = createSurface(); + mClientSurfaceBinder = s->asBinder(); return s; } diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 184edd7..bfe92e6 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -337,7 +337,7 @@ protected: private: mutable Mutex mLock; - mutable wp<Surface> mClientSurface; + mutable bool mHasSurface; wp<IBinder> mClientSurfaceBinder; const wp<Client> mClientRef; // only read diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index d05918f..4ac03a8 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -356,16 +356,6 @@ public class WifiManager { public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; /** - * In this Wi-Fi lock mode, Wi-Fi will behave as in the mode - * {@link #WIFI_MODE_FULL} but it operates at high performance - * at the expense of power. This mode should be used - * only when the wifi connection needs to have minimum loss and low - * latency as it can impact the battery life. - * @hide - */ - public static final int WIFI_MODE_FULL_HIGH_PERF = 3; - - /** * In this Wi-Fi lock mode, Wi-Fi will be kept active, * and will behave normally, i.e., it will attempt to automatically * establish a connection to a remembered access point that is @@ -383,10 +373,29 @@ public class WifiManager { * an application in this mode. */ public static final int WIFI_MODE_SCAN_ONLY = 2; + /** + * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode + * {@link #WIFI_MODE_FULL} but it operates at high performance + * with minimum packet loss and low packet latency even when + * the device screen is off. This mode will consume more power + * and hence should be used only when there is a need for such + * an active connection. + * <p> + * An example use case is when a voice connection needs to be + * kept active even after the device screen goes off. Holding the + * regular {@link #WIFI_MODE_FULL} lock will keep the wifi + * connection active, but the connection can be lossy. + * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the + * duration of the voice call will improve the call quality. + * <p> + * When there is no support from the hardware, this lock mode + * will have the same behavior as {@link #WIFI_MODE_FULL} + */ + public static final int WIFI_MODE_FULL_HIGH_PERF = 3; /** Anything worse than or equal to this will show 0 bars. */ private static final int MIN_RSSI = -100; - + /** Anything better than or equal to this will show the max bars. */ private static final int MAX_RSSI = -55; @@ -1288,9 +1297,10 @@ public class WifiManager { * Creates a new WifiLock. * * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, - * and {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. - * @param tag a tag for the WifiLock to identify it in debugging messages. This string is - * never shown to the user under normal conditions, but should be descriptive + * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for + * descriptions of the types of Wi-Fi locks. + * @param tag a tag for the WifiLock to identify it in debugging messages. This string is + * never shown to the user under normal conditions, but should be descriptive * enough to identify your application and the specific WifiLock within it, if it * holds multiple WifiLocks. * @@ -1301,7 +1311,7 @@ public class WifiManager { public WifiLock createWifiLock(int lockType, String tag) { return new WifiLock(lockType, tag); } - + /** * Creates a new WifiLock. * |