MotionEvent.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.os.SystemClock;
22import android.util.Config;
23
24/**
25 * Object used to report movement (mouse, pen, finger, trackball) events.  This
26 * class may hold either absolute or relative movements, depending on what
27 * it is being used for.
28 */
29public final class MotionEvent implements Parcelable {
30    public static final int ACTION_DOWN             = 0;
31    public static final int ACTION_UP               = 1;
32    public static final int ACTION_MOVE             = 2;
33    public static final int ACTION_CANCEL           = 3;
34
35    private static final boolean TRACK_RECYCLED_LOCATION = false;
36
37    /**
38     * Flag indicating the motion event intersected the top edge of the screen.
39     */
40    public static final int EDGE_TOP = 0x00000001;
41
42    /**
43     * Flag indicating the motion event intersected the bottom edge of the screen.
44     */
45    public static final int EDGE_BOTTOM = 0x00000002;
46
47    /**
48     * Flag indicating the motion event intersected the left edge of the screen.
49     */
50    public static final int EDGE_LEFT = 0x00000004;
51
52    /**
53     * Flag indicating the motion event intersected the right edge of the screen.
54     */
55    public static final int EDGE_RIGHT = 0x00000008;
56
57    static private final int MAX_RECYCLED = 10;
58    static private Object gRecyclerLock = new Object();
59    static private int gRecyclerUsed = 0;
60    static private MotionEvent gRecyclerTop = null;
61
62    private long mDownTime;
63    private long mEventTime;
64    private int mAction;
65    private float mX;
66    private float mY;
67    private float mRawX;
68    private float mRawY;
69    private float mPressure;
70    private float mSize;
71    private int mMetaState;
72    private int mNumHistory;
73    private float[] mHistory;
74    private long[] mHistoryTimes;
75    private float mXPrecision;
76    private float mYPrecision;
77    private int mDeviceId;
78    private int mEdgeFlags;
79
80    private MotionEvent mNext;
81    private RuntimeException mRecycledLocation;
82    private boolean mRecycled;
83
84    private MotionEvent() {
85    }
86
87    static private MotionEvent obtain() {
88        synchronized (gRecyclerLock) {
89            if (gRecyclerTop == null) {
90                return new MotionEvent();
91            }
92            MotionEvent ev = gRecyclerTop;
93            gRecyclerTop = ev.mNext;
94            gRecyclerUsed--;
95            ev.mRecycledLocation = null;
96            ev.mRecycled = false;
97            return ev;
98        }
99    }
100
101    /**
102     * Create a new MotionEvent, filling in all of the basic values that
103     * define the motion.
104     *
105     * @param downTime The time (in ms) when the user originally pressed down to start
106     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
107     * @param eventTime  The the time (in ms) when this specific event was generated.  This
108     * must be obtained from {@link SystemClock#uptimeMillis()}.
109     * @param action The kind of action being performed -- one of either
110     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
111     * {@link #ACTION_CANCEL}.
112     * @param x The X coordinate of this event.
113     * @param y The Y coordinate of this event.
114     * @param pressure The current pressure of this event.  The pressure generally
115     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
116     * values higher than 1 may be generated depending on the calibration of
117     * the input device.
118     * @param size A scaled value of the approximate size of the area being pressed when
119     * touched with the finger. The actual value in pixels corresponding to the finger
120     * touch is normalized with a device specific range of values
121     * and scaled to a value between 0 and 1.
122     * @param metaState The state of any meta / modifier keys that were in effect when
123     * the event was generated.
124     * @param xPrecision The precision of the X coordinate being reported.
125     * @param yPrecision The precision of the Y coordinate being reported.
126     * @param deviceId The id for the device that this event came from.  An id of
127     * zero indicates that the event didn't come from a physical device; other
128     * numbers are arbitrary and you shouldn't depend on the values.
129     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
130     * MotionEvent.
131     */
132    static public MotionEvent obtain(long downTime, long eventTime, int action,
133            float x, float y, float pressure, float size, int metaState,
134            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
135        MotionEvent ev = obtain();
136        ev.mDeviceId = deviceId;
137        ev.mEdgeFlags = edgeFlags;
138        ev.mDownTime = downTime;
139        ev.mEventTime = eventTime;
140        ev.mAction = action;
141        ev.mX = ev.mRawX = x;
142        ev.mY = ev.mRawY = y;
143        ev.mPressure = pressure;
144        ev.mSize = size;
145        ev.mMetaState = metaState;
146        ev.mXPrecision = xPrecision;
147        ev.mYPrecision = yPrecision;
148
149        return ev;
150    }
151
152    /**
153     * Create a new MotionEvent, filling in a subset of the basic motion
154     * values.  Those not specified here are: device id (always 0), pressure
155     * and size (always 1), x and y precision (always 1), and edgeFlags (always 0).
156     *
157     * @param downTime The time (in ms) when the user originally pressed down to start
158     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
159     * @param eventTime  The the time (in ms) when this specific event was generated.  This
160     * must be obtained from {@link SystemClock#uptimeMillis()}.
161     * @param action The kind of action being performed -- one of either
162     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
163     * {@link #ACTION_CANCEL}.
164     * @param x The X coordinate of this event.
165     * @param y The Y coordinate of this event.
166     * @param metaState The state of any meta / modifier keys that were in effect when
167     * the event was generated.
168     */
169    static public MotionEvent obtain(long downTime, long eventTime, int action,
170            float x, float y, int metaState) {
171        MotionEvent ev = obtain();
172        ev.mDeviceId = 0;
173        ev.mEdgeFlags = 0;
174        ev.mDownTime = downTime;
175        ev.mEventTime = eventTime;
176        ev.mAction = action;
177        ev.mX = ev.mRawX = x;
178        ev.mY = ev.mRawY = y;
179        ev.mPressure = 1.0f;
180        ev.mSize = 1.0f;
181        ev.mMetaState = metaState;
182        ev.mXPrecision = 1.0f;
183        ev.mYPrecision = 1.0f;
184
185        return ev;
186    }
187
188    /**
189     * Create a new MotionEvent, copying from an existing one.
190     */
191    static public MotionEvent obtain(MotionEvent o) {
192        MotionEvent ev = obtain();
193        ev.mDeviceId = o.mDeviceId;
194        ev.mEdgeFlags = o.mEdgeFlags;
195        ev.mDownTime = o.mDownTime;
196        ev.mEventTime = o.mEventTime;
197        ev.mAction = o.mAction;
198        ev.mX = o.mX;
199        ev.mRawX = o.mRawX;
200        ev.mY = o.mY;
201        ev.mRawY = o.mRawY;
202        ev.mPressure = o.mPressure;
203        ev.mSize = o.mSize;
204        ev.mMetaState = o.mMetaState;
205        ev.mXPrecision = o.mXPrecision;
206        ev.mYPrecision = o.mYPrecision;
207        final int N = o.mNumHistory;
208        ev.mNumHistory = N;
209        if (N > 0) {
210            // could be more efficient about this...
211            ev.mHistory = (float[])o.mHistory.clone();
212            ev.mHistoryTimes = (long[])o.mHistoryTimes.clone();
213        }
214        return ev;
215    }
216
217    /**
218     * Recycle the MotionEvent, to be re-used by a later caller.  After calling
219     * this function you must not ever touch the event again.
220     */
221    public void recycle() {
222        // Ensure recycle is only called once!
223        if (TRACK_RECYCLED_LOCATION) {
224            if (mRecycledLocation != null) {
225                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
226            }
227            mRecycledLocation = new RuntimeException("Last recycled here");
228        } else if (mRecycled) {
229            throw new RuntimeException(toString() + " recycled twice!");
230        }
231
232        //Log.w("MotionEvent", "Recycling event " + this, mRecycledLocation);
233        synchronized (gRecyclerLock) {
234            if (gRecyclerUsed < MAX_RECYCLED) {
235                gRecyclerUsed++;
236                mNumHistory = 0;
237                mNext = gRecyclerTop;
238                gRecyclerTop = this;
239            }
240        }
241    }
242
243    /**
244     * Return the kind of action being performed -- one of either
245     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
246     * {@link #ACTION_CANCEL}.
247     */
248    public final int getAction() {
249        return mAction;
250    }
251
252    /**
253     * Returns the time (in ms) when the user originally pressed down to start
254     * a stream of position events.
255     */
256    public final long getDownTime() {
257        return mDownTime;
258    }
259
260    /**
261     * Returns the time (in ms) when this specific event was generated.
262     */
263    public final long getEventTime() {
264        return mEventTime;
265    }
266
267    /**
268     * Returns the X coordinate of this event.  Whole numbers are pixels; the
269     * value may have a fraction for input devices that are sub-pixel precise.
270     */
271    public final float getX() {
272        return mX;
273    }
274
275    /**
276     * Returns the Y coordinate of this event.  Whole numbers are pixels; the
277     * value may have a fraction for input devices that are sub-pixel precise.
278     */
279    public final float getY() {
280        return mY;
281    }
282
283    /**
284     * Returns the current pressure of this event.  The pressure generally
285     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
286     * values higher than 1 may be generated depending on the calibration of
287     * the input device.
288     */
289    public final float getPressure() {
290        return mPressure;
291    }
292
293    /**
294     * Returns a scaled value of the approximate size, of the area being pressed when
295     * touched with the finger. The actual value in pixels corresponding to the finger
296     * touch  is normalized with the device specific range of values
297     * and scaled to a value between 0 and 1. The value of size can be used to
298     * determine fat touch events.
299     */
300    public final float getSize() {
301        return mSize;
302    }
303
304    /**
305     * Returns the state of any meta / modifier keys that were in effect when
306     * the event was generated.  This is the same values as those
307     * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}.
308     *
309     * @return an integer in which each bit set to 1 represents a pressed
310     *         meta key
311     *
312     * @see KeyEvent#getMetaState()
313     */
314    public final int getMetaState() {
315        return mMetaState;
316    }
317
318    /**
319     * Returns the original raw X coordinate of this event.  For touch
320     * events on the screen, this is the original location of the event
321     * on the screen, before it had been adjusted for the containing window
322     * and views.
323     */
324    public final float getRawX() {
325        return mRawX;
326    }
327
328    /**
329     * Returns the original raw Y coordinate of this event.  For touch
330     * events on the screen, this is the original location of the event
331     * on the screen, before it had been adjusted for the containing window
332     * and views.
333     */
334    public final float getRawY() {
335        return mRawY;
336    }
337
338    /**
339     * Return the precision of the X coordinates being reported.  You can
340     * multiple this number with {@link #getX} to find the actual hardware
341     * value of the X coordinate.
342     * @return Returns the precision of X coordinates being reported.
343     */
344    public final float getXPrecision() {
345        return mXPrecision;
346    }
347
348    /**
349     * Return the precision of the Y coordinates being reported.  You can
350     * multiple this number with {@link #getY} to find the actual hardware
351     * value of the Y coordinate.
352     * @return Returns the precision of Y coordinates being reported.
353     */
354    public final float getYPrecision() {
355        return mYPrecision;
356    }
357
358    /**
359     * Returns the number of historical points in this event.  These are
360     * movements that have occurred between this event and the previous event.
361     * This only applies to ACTION_MOVE events -- all other actions will have
362     * a size of 0.
363     *
364     * @return Returns the number of historical points in the event.
365     */
366    public final int getHistorySize() {
367        return mNumHistory;
368    }
369
370    /**
371     * Returns the time that a historical movement occurred between this event
372     * and the previous event.  Only applies to ACTION_MOVE events.
373     *
374     * @param pos Which historical value to return; must be less than
375     * {@link #getHistorySize}
376     *
377     * @see #getHistorySize
378     * @see #getEventTime
379     */
380    public final long getHistoricalEventTime(int pos) {
381        return mHistoryTimes[pos];
382    }
383
384    /**
385     * Returns a historical X coordinate that occurred between this event
386     * and the previous event.  Only applies to ACTION_MOVE events.
387     *
388     * @param pos Which historical value to return; must be less than
389     * {@link #getHistorySize}
390     *
391     * @see #getHistorySize
392     * @see #getX
393     */
394    public final float getHistoricalX(int pos) {
395        return mHistory[pos*4];
396    }
397
398    /**
399     * Returns a historical Y coordinate that occurred between this event
400     * and the previous event.  Only applies to ACTION_MOVE events.
401     *
402     * @param pos Which historical value to return; must be less than
403     * {@link #getHistorySize}
404     *
405     * @see #getHistorySize
406     * @see #getY
407     */
408    public final float getHistoricalY(int pos) {
409        return mHistory[pos*4 + 1];
410    }
411
412    /**
413     * Returns a historical pressure coordinate that occurred between this event
414     * and the previous event.  Only applies to ACTION_MOVE events.
415     *
416     * @param pos Which historical value to return; must be less than
417     * {@link #getHistorySize}
418     *
419     * @see #getHistorySize
420     * @see #getPressure
421     */
422    public final float getHistoricalPressure(int pos) {
423        return mHistory[pos*4 + 2];
424    }
425
426    /**
427     * Returns a historical size coordinate that occurred between this event
428     * and the previous event.  Only applies to ACTION_MOVE events.
429     *
430     * @param pos Which historical value to return; must be less than
431     * {@link #getHistorySize}
432     *
433     * @see #getHistorySize
434     * @see #getSize
435     */
436    public final float getHistoricalSize(int pos) {
437        return mHistory[pos*4 + 3];
438    }
439
440    /**
441     * Return the id for the device that this event came from.  An id of
442     * zero indicates that the event didn't come from a physical device; other
443     * numbers are arbitrary and you shouldn't depend on the values.
444     */
445    public final int getDeviceId() {
446        return mDeviceId;
447    }
448
449    /**
450     * Returns a bitfield indicating which edges, if any, where touched by this
451     * MotionEvent. For touch events, clients can use this to determine if the
452     * user's finger was touching the edge of the display.
453     *
454     * @see #EDGE_LEFT
455     * @see #EDGE_TOP
456     * @see #EDGE_RIGHT
457     * @see #EDGE_BOTTOM
458     */
459    public final int getEdgeFlags() {
460        return mEdgeFlags;
461    }
462
463
464    /**
465     * Sets the bitfield indicating which edges, if any, where touched by this
466     * MotionEvent.
467     *
468     * @see #getEdgeFlags()
469     */
470    public final void setEdgeFlags(int flags) {
471        mEdgeFlags = flags;
472    }
473
474    /**
475     * Sets this event's action.
476     */
477    public final void setAction(int action) {
478        mAction = action;
479    }
480
481    /**
482     * Adjust this event's location.
483     * @param deltaX Amount to add to the current X coordinate of the event.
484     * @param deltaY Amount to add to the current Y coordinate of the event.
485     */
486    public final void offsetLocation(float deltaX, float deltaY) {
487        mX += deltaX;
488        mY += deltaY;
489        final int N = mNumHistory*4;
490        if (N <= 0) {
491            return;
492        }
493        final float[] pos = mHistory;
494        for (int i=0; i<N; i+=4) {
495            pos[i] += deltaX;
496            pos[i+1] += deltaY;
497        }
498    }
499
500    /**
501     * Set this event's location.  Applies {@link #offsetLocation} with a
502     * delta from the current location to the given new location.
503     *
504     * @param x New absolute X location.
505     * @param y New absolute Y location.
506     */
507    public final void setLocation(float x, float y) {
508        float deltaX = x-mX;
509        float deltaY = y-mY;
510        if (deltaX != 0 || deltaY != 0) {
511            offsetLocation(deltaX, deltaY);
512        }
513    }
514
515    /**
516     * Add a new movement to the batch of movements in this event.  The event's
517     * current location, position and size is updated to the new values.  In
518     * the future, the current values in the event will be added to a list of
519     * historic values.
520     *
521     * @param x The new X position.
522     * @param y The new Y position.
523     * @param pressure The new pressure.
524     * @param size The new size.
525     */
526    public final void addBatch(long eventTime, float x, float y,
527            float pressure, float size, int metaState) {
528        float[] history = mHistory;
529        long[] historyTimes = mHistoryTimes;
530        int N;
531        int avail;
532        if (history == null) {
533            mHistory = history = new float[8*4];
534            mHistoryTimes = historyTimes = new long[8];
535            mNumHistory = N = 0;
536            avail = 8;
537        } else {
538            N = mNumHistory;
539            avail = history.length/4;
540            if (N == avail) {
541                avail += 8;
542                float[] newHistory = new float[avail*4];
543                System.arraycopy(history, 0, newHistory, 0, N*4);
544                mHistory = history = newHistory;
545                long[] newHistoryTimes = new long[avail];
546                System.arraycopy(historyTimes, 0, newHistoryTimes, 0, N);
547                mHistoryTimes = historyTimes = newHistoryTimes;
548            }
549        }
550
551        historyTimes[N] = mEventTime;
552
553        final int pos = N*4;
554        history[pos] = mX;
555        history[pos+1] = mY;
556        history[pos+2] = mPressure;
557        history[pos+3] = mSize;
558        mNumHistory = N+1;
559
560        mEventTime = eventTime;
561        mX = mRawX = x;
562        mY = mRawY = y;
563        mPressure = pressure;
564        mSize = size;
565        mMetaState |= metaState;
566    }
567
568    @Override
569    public String toString() {
570        return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
571            + " action=" + mAction + " x=" + mX
572            + " y=" + mY + " pressure=" + mPressure + " size=" + mSize + "}";
573    }
574
575    public static final Parcelable.Creator<MotionEvent> CREATOR
576            = new Parcelable.Creator<MotionEvent>() {
577        public MotionEvent createFromParcel(Parcel in) {
578            MotionEvent ev = obtain();
579            ev.readFromParcel(in);
580            return ev;
581        }
582
583        public MotionEvent[] newArray(int size) {
584            return new MotionEvent[size];
585        }
586    };
587
588    public int describeContents() {
589        return 0;
590    }
591
592    public void writeToParcel(Parcel out, int flags) {
593        out.writeLong(mDownTime);
594        out.writeLong(mEventTime);
595        out.writeInt(mAction);
596        out.writeFloat(mX);
597        out.writeFloat(mY);
598        out.writeFloat(mPressure);
599        out.writeFloat(mSize);
600        out.writeInt(mMetaState);
601        out.writeFloat(mRawX);
602        out.writeFloat(mRawY);
603        final int N = mNumHistory;
604        out.writeInt(N);
605        if (N > 0) {
606            final int N4 = N*4;
607            int i;
608            float[] history = mHistory;
609            for (i=0; i<N4; i++) {
610                out.writeFloat(history[i]);
611            }
612            long[] times = mHistoryTimes;
613            for (i=0; i<N; i++) {
614                out.writeLong(times[i]);
615            }
616        }
617        out.writeFloat(mXPrecision);
618        out.writeFloat(mYPrecision);
619        out.writeInt(mDeviceId);
620        out.writeInt(mEdgeFlags);
621    }
622
623    private void readFromParcel(Parcel in) {
624        mDownTime = in.readLong();
625        mEventTime = in.readLong();
626        mAction = in.readInt();
627        mX = in.readFloat();
628        mY = in.readFloat();
629        mPressure = in.readFloat();
630        mSize = in.readFloat();
631        mMetaState = in.readInt();
632        mRawX = in.readFloat();
633        mRawY = in.readFloat();
634        final int N = in.readInt();
635        if ((mNumHistory=N) > 0) {
636            final int N4 = N*4;
637            float[] history = mHistory;
638            if (history == null || history.length < N4) {
639                mHistory = history = new float[N4 + (4*4)];
640            }
641            for (int i=0; i<N4; i++) {
642                history[i] = in.readFloat();
643            }
644            long[] times = mHistoryTimes;
645            if (times == null || times.length < N) {
646                mHistoryTimes = times = new long[N + 4];
647            }
648            for (int i=0; i<N; i++) {
649                times[i] = in.readLong();
650            }
651        }
652        mXPrecision = in.readFloat();
653        mYPrecision = in.readFloat();
654        mDeviceId = in.readInt();
655        mEdgeFlags = in.readInt();
656    }
657
658}
659
660