MotionEvent.java revision ecf2b68d834d334de218dc427615b4ca05c0293a
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;
22
23/**
24 * Object used to report movement (mouse, pen, finger, trackball) events.  This
25 * class may hold either absolute or relative movements, depending on what
26 * it is being used for.
27 */
28public final class MotionEvent implements Parcelable {
29    /**
30     * Constant for {@link #getAction}: A pressed gesture has started, the
31     * motion contains the initial starting location.
32     */
33    public static final int ACTION_DOWN             = 0;
34    /**
35     * Constant for {@link #getAction}: A pressed gesture has finished, the
36     * motion contains the final release location as well as any intermediate
37     * points since the last down or move event.
38     */
39    public static final int ACTION_UP               = 1;
40    /**
41     * Constant for {@link #getAction}: A change has happened during a
42     * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
43     * The motion contains the most recent point, as well as any intermediate
44     * points since the last down or move event.
45     */
46    public static final int ACTION_MOVE             = 2;
47    /**
48     * Constant for {@link #getAction}: The current gesture has been aborted.
49     * You will not receive any more points in it.  You should treat this as
50     * an up event, but not perform any action that you normally would.
51     */
52    public static final int ACTION_CANCEL           = 3;
53    /**
54     * Constant for {@link #getAction}: A movement has happened outside of the
55     * normal bounds of the UI element.  This does not provide a full gesture,
56     * but only the initial location of the movement/touch.
57     */
58    public static final int ACTION_OUTSIDE          = 4;
59
60    private static final boolean TRACK_RECYCLED_LOCATION = false;
61
62    /**
63     * Flag indicating the motion event intersected the top edge of the screen.
64     */
65    public static final int EDGE_TOP = 0x00000001;
66
67    /**
68     * Flag indicating the motion event intersected the bottom edge of the screen.
69     */
70    public static final int EDGE_BOTTOM = 0x00000002;
71
72    /**
73     * Flag indicating the motion event intersected the left edge of the screen.
74     */
75    public static final int EDGE_LEFT = 0x00000004;
76
77    /**
78     * Flag indicating the motion event intersected the right edge of the screen.
79     */
80    public static final int EDGE_RIGHT = 0x00000008;
81
82    static private final int MAX_RECYCLED = 10;
83    static private Object gRecyclerLock = new Object();
84    static private int gRecyclerUsed = 0;
85    static private MotionEvent gRecyclerTop = null;
86
87    private long mDownTime;
88    private long mEventTime;
89    private long mEventTimeNano;
90    private int mAction;
91    private float mX;
92    private float mY;
93    private float mRawX;
94    private float mRawY;
95    private float mPressure;
96    private float mSize;
97    private int mMetaState;
98    private int mNumHistory;
99    private float[] mHistory;
100    private long[] mHistoryTimes;
101    private float mXPrecision;
102    private float mYPrecision;
103    private int mDeviceId;
104    private int mEdgeFlags;
105
106    private MotionEvent mNext;
107    private RuntimeException mRecycledLocation;
108    private boolean mRecycled;
109
110    private MotionEvent() {
111    }
112
113    static private MotionEvent obtain() {
114        synchronized (gRecyclerLock) {
115            if (gRecyclerTop == null) {
116                return new MotionEvent();
117            }
118            MotionEvent ev = gRecyclerTop;
119            gRecyclerTop = ev.mNext;
120            gRecyclerUsed--;
121            ev.mRecycledLocation = null;
122            ev.mRecycled = false;
123            return ev;
124        }
125    }
126
127    /**
128     * Create a new MotionEvent, filling in all of the basic values that
129     * define the motion.
130     *
131     * @param downTime The time (in ms) when the user originally pressed down to start
132     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
133     * @param eventTime  The the time (in ms) when this specific event was generated.  This
134     * must be obtained from {@link SystemClock#uptimeMillis()}.
135     * @param eventTimeNano  The the time (in ns) when this specific event was generated.  This
136     * must be obtained from {@link System#nanoTime()}.
137     * @param action The kind of action being performed -- one of either
138     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
139     * {@link #ACTION_CANCEL}.
140     * @param x The X coordinate of this event.
141     * @param y The Y coordinate of this event.
142     * @param pressure The current pressure of this event.  The pressure generally
143     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
144     * values higher than 1 may be generated depending on the calibration of
145     * the input device.
146     * @param size A scaled value of the approximate size of the area being pressed when
147     * touched with the finger. The actual value in pixels corresponding to the finger
148     * touch is normalized with a device specific range of values
149     * and scaled to a value between 0 and 1.
150     * @param metaState The state of any meta / modifier keys that were in effect when
151     * the event was generated.
152     * @param xPrecision The precision of the X coordinate being reported.
153     * @param yPrecision The precision of the Y coordinate being reported.
154     * @param deviceId The id for the device that this event came from.  An id of
155     * zero indicates that the event didn't come from a physical device; other
156     * numbers are arbitrary and you shouldn't depend on the values.
157     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
158     * MotionEvent.
159     *
160     * @hide
161     */
162    static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
163            int action, float x, float y, float pressure, float size, int metaState,
164            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
165        MotionEvent ev = obtain();
166        ev.mDeviceId = deviceId;
167        ev.mEdgeFlags = edgeFlags;
168        ev.mDownTime = downTime;
169        ev.mEventTime = eventTime;
170        ev.mEventTimeNano = eventTimeNano;
171        ev.mAction = action;
172        ev.mX = ev.mRawX = x;
173        ev.mY = ev.mRawY = y;
174        ev.mPressure = pressure;
175        ev.mSize = size;
176        ev.mMetaState = metaState;
177        ev.mXPrecision = xPrecision;
178        ev.mYPrecision = yPrecision;
179
180        return ev;
181    }
182
183    /**
184     * Create a new MotionEvent, filling in all of the basic values that
185     * define the motion.
186     *
187     * @param downTime The time (in ms) when the user originally pressed down to start
188     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
189     * @param eventTime  The the time (in ms) when this specific event was generated.  This
190     * must be obtained from {@link SystemClock#uptimeMillis()}.
191     * @param action The kind of action being performed -- one of either
192     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
193     * {@link #ACTION_CANCEL}.
194     * @param x The X coordinate of this event.
195     * @param y The Y coordinate of this event.
196     * @param pressure The current pressure of this event.  The pressure generally
197     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
198     * values higher than 1 may be generated depending on the calibration of
199     * the input device.
200     * @param size A scaled value of the approximate size of the area being pressed when
201     * touched with the finger. The actual value in pixels corresponding to the finger
202     * touch is normalized with a device specific range of values
203     * and scaled to a value between 0 and 1.
204     * @param metaState The state of any meta / modifier keys that were in effect when
205     * the event was generated.
206     * @param xPrecision The precision of the X coordinate being reported.
207     * @param yPrecision The precision of the Y coordinate being reported.
208     * @param deviceId The id for the device that this event came from.  An id of
209     * zero indicates that the event didn't come from a physical device; other
210     * numbers are arbitrary and you shouldn't depend on the values.
211     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
212     * MotionEvent.
213     */
214    static public MotionEvent obtain(long downTime, long eventTime, int action,
215            float x, float y, float pressure, float size, int metaState,
216            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
217        MotionEvent ev = obtain();
218        ev.mDeviceId = deviceId;
219        ev.mEdgeFlags = edgeFlags;
220        ev.mDownTime = downTime;
221        ev.mEventTime = eventTime;
222        ev.mEventTimeNano = eventTime * 1000000;
223        ev.mAction = action;
224        ev.mX = ev.mRawX = x;
225        ev.mY = ev.mRawY = y;
226        ev.mPressure = pressure;
227        ev.mSize = size;
228        ev.mMetaState = metaState;
229        ev.mXPrecision = xPrecision;
230        ev.mYPrecision = yPrecision;
231
232        return ev;
233    }
234
235    /**
236     * Create a new MotionEvent, filling in a subset of the basic motion
237     * values.  Those not specified here are: device id (always 0), pressure
238     * and size (always 1), x and y precision (always 1), and edgeFlags (always 0).
239     *
240     * @param downTime The time (in ms) when the user originally pressed down to start
241     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
242     * @param eventTime  The the time (in ms) when this specific event was generated.  This
243     * must be obtained from {@link SystemClock#uptimeMillis()}.
244     * @param action 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     * @param x The X coordinate of this event.
248     * @param y The Y coordinate of this event.
249     * @param metaState The state of any meta / modifier keys that were in effect when
250     * the event was generated.
251     */
252    static public MotionEvent obtain(long downTime, long eventTime, int action,
253            float x, float y, int metaState) {
254        MotionEvent ev = obtain();
255        ev.mDeviceId = 0;
256        ev.mEdgeFlags = 0;
257        ev.mDownTime = downTime;
258        ev.mEventTime = eventTime;
259        ev.mEventTimeNano = eventTime * 1000000;
260        ev.mAction = action;
261        ev.mX = ev.mRawX = x;
262        ev.mY = ev.mRawY = y;
263        ev.mPressure = 1.0f;
264        ev.mSize = 1.0f;
265        ev.mMetaState = metaState;
266        ev.mXPrecision = 1.0f;
267        ev.mYPrecision = 1.0f;
268
269        return ev;
270    }
271
272    /**
273     * Scales down the coordination of this event by the given scale.
274     *
275     * @hide
276     */
277    public void scale(float scale) {
278        mX *= scale;
279        mY *= scale;
280        mRawX *= scale;
281        mRawY *= scale;
282        mSize *= scale;
283        mXPrecision *= scale;
284        mYPrecision *= scale;
285        if (mHistory != null) {
286            float[] history = mHistory;
287            int length = history.length;
288            for (int i = 0; i < length; i += 4) {
289                history[i] *= scale;        // X
290                history[i + 1] *= scale;    // Y
291                // no need to scale pressure ([i+2])
292                history[i + 3] *= scale;    // Size, TODO: square this?
293            }
294        }
295    }
296
297    /**
298     * Translate the coordination of the event by given x and y.
299     *
300     * @hide
301     */
302    public void translate(float dx, float dy) {
303        mX += dx;
304        mY += dy;
305        mRawX += dx;
306        mRawY += dx;
307        if (mHistory != null) {
308            float[] history = mHistory;
309            int length = history.length;
310            for (int i = 0; i < length; i += 4) {
311                history[i] += dx;        // X
312                history[i + 1] += dy;    // Y
313                // no need to translate pressure (i+2) and size (i+3)
314            }
315        }
316    }
317
318    /**
319     * Create a new MotionEvent, copying from an existing one.
320     */
321    static public MotionEvent obtain(MotionEvent o) {
322        MotionEvent ev = obtain();
323        ev.mDeviceId = o.mDeviceId;
324        ev.mEdgeFlags = o.mEdgeFlags;
325        ev.mDownTime = o.mDownTime;
326        ev.mEventTime = o.mEventTime;
327        ev.mEventTimeNano = o.mEventTimeNano;
328        ev.mAction = o.mAction;
329        ev.mX = o.mX;
330        ev.mRawX = o.mRawX;
331        ev.mY = o.mY;
332        ev.mRawY = o.mRawY;
333        ev.mPressure = o.mPressure;
334        ev.mSize = o.mSize;
335        ev.mMetaState = o.mMetaState;
336        ev.mXPrecision = o.mXPrecision;
337        ev.mYPrecision = o.mYPrecision;
338        final int N = o.mNumHistory;
339        ev.mNumHistory = N;
340        if (N > 0) {
341            // could be more efficient about this...
342            ev.mHistory = (float[])o.mHistory.clone();
343            ev.mHistoryTimes = (long[])o.mHistoryTimes.clone();
344        }
345        return ev;
346    }
347
348    /**
349     * Recycle the MotionEvent, to be re-used by a later caller.  After calling
350     * this function you must not ever touch the event again.
351     */
352    public void recycle() {
353        // Ensure recycle is only called once!
354        if (TRACK_RECYCLED_LOCATION) {
355            if (mRecycledLocation != null) {
356                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
357            }
358            mRecycledLocation = new RuntimeException("Last recycled here");
359        } else if (mRecycled) {
360            throw new RuntimeException(toString() + " recycled twice!");
361        }
362
363        //Log.w("MotionEvent", "Recycling event " + this, mRecycledLocation);
364        synchronized (gRecyclerLock) {
365            if (gRecyclerUsed < MAX_RECYCLED) {
366                gRecyclerUsed++;
367                mNumHistory = 0;
368                mNext = gRecyclerTop;
369                gRecyclerTop = this;
370            }
371        }
372    }
373
374    /**
375     * Return the kind of action being performed -- one of either
376     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
377     * {@link #ACTION_CANCEL}.
378     */
379    public final int getAction() {
380        return mAction;
381    }
382
383    /**
384     * Returns the time (in ms) when the user originally pressed down to start
385     * a stream of position events.
386     */
387    public final long getDownTime() {
388        return mDownTime;
389    }
390
391    /**
392     * Returns the time (in ms) when this specific event was generated.
393     */
394    public final long getEventTime() {
395        return mEventTime;
396    }
397
398    /**
399<<<<<<< HEAD:core/java/android/view/MotionEvent.java
400     * Returns the time (in ns) when this specific event was generated.
401     * The value is in nanosecond precision but it may not have nanosecond accuracy.
402     *
403     * @hide
404     */
405    public final long getEventTimeNano() {
406        return mEventTimeNano;
407    }
408
409    /**
410     * Returns the X coordinate of this event.  Whole numbers are pixels; the
411     * value may have a fraction for input devices that are sub-pixel precise.
412|||||||
413     * Returns the X coordinate of this event.  Whole numbers are pixels; the
414     * value may have a fraction for input devices that are sub-pixel precise.
415=======
416     * Returns the X coordinate of this event.  Whole numbers are pixels; the
417     * value may have a fraction for input devices that are sub-pixel precise.
418>>>>>>> cafdea61a85c8f5d0646cc9413a09346c637f43f:core/java/android/view/MotionEvent.java
419     */
420    public final float getX() {
421        return mX;
422    }
423
424    /**
425     * Returns the Y coordinate of this event.  Whole numbers are pixels; the
426     * value may have a fraction for input devices that are sub-pixel precise.
427     */
428    public final float getY() {
429        return mY;
430    }
431
432    /**
433     * Returns the current pressure of this event.  The pressure generally
434     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
435     * values higher than 1 may be generated depending on the calibration of
436     * the input device.
437     */
438    public final float getPressure() {
439        return mPressure;
440    }
441
442    /**
443     * Returns a scaled value of the approximate size, of the area being pressed when
444     * touched with the finger. The actual value in pixels corresponding to the finger
445     * touch  is normalized with the device specific range of values
446     * and scaled to a value between 0 and 1. The value of size can be used to
447     * determine fat touch events.
448     */
449    public final float getSize() {
450        return mSize;
451    }
452
453    /**
454     * Returns the state of any meta / modifier keys that were in effect when
455     * the event was generated.  This is the same values as those
456     * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}.
457     *
458     * @return an integer in which each bit set to 1 represents a pressed
459     *         meta key
460     *
461     * @see KeyEvent#getMetaState()
462     */
463    public final int getMetaState() {
464        return mMetaState;
465    }
466
467    /**
468     * Returns the original raw X coordinate of this event.  For touch
469     * events on the screen, this is the original location of the event
470     * on the screen, before it had been adjusted for the containing window
471     * and views.
472     */
473    public final float getRawX() {
474        return mRawX;
475    }
476
477    /**
478     * Returns the original raw Y coordinate of this event.  For touch
479     * events on the screen, this is the original location of the event
480     * on the screen, before it had been adjusted for the containing window
481     * and views.
482     */
483    public final float getRawY() {
484        return mRawY;
485    }
486
487    /**
488     * Return the precision of the X coordinates being reported.  You can
489     * multiple this number with {@link #getX} to find the actual hardware
490     * value of the X coordinate.
491     * @return Returns the precision of X coordinates being reported.
492     */
493    public final float getXPrecision() {
494        return mXPrecision;
495    }
496
497    /**
498     * Return the precision of the Y coordinates being reported.  You can
499     * multiple this number with {@link #getY} to find the actual hardware
500     * value of the Y coordinate.
501     * @return Returns the precision of Y coordinates being reported.
502     */
503    public final float getYPrecision() {
504        return mYPrecision;
505    }
506
507    /**
508     * Returns the number of historical points in this event.  These are
509     * movements that have occurred between this event and the previous event.
510     * This only applies to ACTION_MOVE events -- all other actions will have
511     * a size of 0.
512     *
513     * @return Returns the number of historical points in the event.
514     */
515    public final int getHistorySize() {
516        return mNumHistory;
517    }
518
519    /**
520     * Returns the time that a historical movement occurred between this event
521     * and the previous event.  Only applies to ACTION_MOVE events.
522     *
523     * @param pos Which historical value to return; must be less than
524     * {@link #getHistorySize}
525     *
526     * @see #getHistorySize
527     * @see #getEventTime
528     */
529    public final long getHistoricalEventTime(int pos) {
530        return mHistoryTimes[pos];
531    }
532
533    /**
534     * Returns a historical X coordinate that occurred between this event
535     * and the previous event.  Only applies to ACTION_MOVE events.
536     *
537     * @param pos Which historical value to return; must be less than
538     * {@link #getHistorySize}
539     *
540     * @see #getHistorySize
541     * @see #getX
542     */
543    public final float getHistoricalX(int pos) {
544        return mHistory[pos*4];
545    }
546
547    /**
548     * Returns a historical Y coordinate that occurred between this event
549     * and the previous event.  Only applies to ACTION_MOVE events.
550     *
551     * @param pos Which historical value to return; must be less than
552     * {@link #getHistorySize}
553     *
554     * @see #getHistorySize
555     * @see #getY
556     */
557    public final float getHistoricalY(int pos) {
558        return mHistory[pos*4 + 1];
559    }
560
561    /**
562     * Returns a historical pressure coordinate that occurred between this event
563     * and the previous event.  Only applies to ACTION_MOVE events.
564     *
565     * @param pos Which historical value to return; must be less than
566     * {@link #getHistorySize}
567     *
568     * @see #getHistorySize
569     * @see #getPressure
570     */
571    public final float getHistoricalPressure(int pos) {
572        return mHistory[pos*4 + 2];
573    }
574
575    /**
576     * Returns a historical size coordinate that occurred between this event
577     * and the previous event.  Only applies to ACTION_MOVE events.
578     *
579     * @param pos Which historical value to return; must be less than
580     * {@link #getHistorySize}
581     *
582     * @see #getHistorySize
583     * @see #getSize
584     */
585    public final float getHistoricalSize(int pos) {
586        return mHistory[pos*4 + 3];
587    }
588
589    /**
590     * Return the id for the device that this event came from.  An id of
591     * zero indicates that the event didn't come from a physical device; other
592     * numbers are arbitrary and you shouldn't depend on the values.
593     */
594    public final int getDeviceId() {
595        return mDeviceId;
596    }
597
598    /**
599     * Returns a bitfield indicating which edges, if any, where touched by this
600     * MotionEvent. For touch events, clients can use this to determine if the
601     * user's finger was touching the edge of the display.
602     *
603     * @see #EDGE_LEFT
604     * @see #EDGE_TOP
605     * @see #EDGE_RIGHT
606     * @see #EDGE_BOTTOM
607     */
608    public final int getEdgeFlags() {
609        return mEdgeFlags;
610    }
611
612
613    /**
614     * Sets the bitfield indicating which edges, if any, where touched by this
615     * MotionEvent.
616     *
617     * @see #getEdgeFlags()
618     */
619    public final void setEdgeFlags(int flags) {
620        mEdgeFlags = flags;
621    }
622
623    /**
624     * Sets this event's action.
625     */
626    public final void setAction(int action) {
627        mAction = action;
628    }
629
630    /**
631     * Adjust this event's location.
632     * @param deltaX Amount to add to the current X coordinate of the event.
633     * @param deltaY Amount to add to the current Y coordinate of the event.
634     */
635    public final void offsetLocation(float deltaX, float deltaY) {
636        mX += deltaX;
637        mY += deltaY;
638        final int N = mNumHistory*4;
639        if (N <= 0) {
640            return;
641        }
642        final float[] pos = mHistory;
643        for (int i=0; i<N; i+=4) {
644            pos[i] += deltaX;
645            pos[i+1] += deltaY;
646        }
647    }
648
649    /**
650     * Set this event's location.  Applies {@link #offsetLocation} with a
651     * delta from the current location to the given new location.
652     *
653     * @param x New absolute X location.
654     * @param y New absolute Y location.
655     */
656    public final void setLocation(float x, float y) {
657        float deltaX = x-mX;
658        float deltaY = y-mY;
659        if (deltaX != 0 || deltaY != 0) {
660            offsetLocation(deltaX, deltaY);
661        }
662    }
663
664    /**
665     * Add a new movement to the batch of movements in this event.  The event's
666     * current location, position and size is updated to the new values.  In
667     * the future, the current values in the event will be added to a list of
668     * historic values.
669     *
670     * @param x The new X position.
671     * @param y The new Y position.
672     * @param pressure The new pressure.
673     * @param size The new size.
674     */
675    public final void addBatch(long eventTime, float x, float y,
676            float pressure, float size, int metaState) {
677        float[] history = mHistory;
678        long[] historyTimes = mHistoryTimes;
679        int N;
680        int avail;
681        if (history == null) {
682            mHistory = history = new float[8*4];
683            mHistoryTimes = historyTimes = new long[8];
684            mNumHistory = N = 0;
685            avail = 8;
686        } else {
687            N = mNumHistory;
688            avail = history.length/4;
689            if (N == avail) {
690                avail += 8;
691                float[] newHistory = new float[avail*4];
692                System.arraycopy(history, 0, newHistory, 0, N*4);
693                mHistory = history = newHistory;
694                long[] newHistoryTimes = new long[avail];
695                System.arraycopy(historyTimes, 0, newHistoryTimes, 0, N);
696                mHistoryTimes = historyTimes = newHistoryTimes;
697            }
698        }
699
700        historyTimes[N] = mEventTime;
701
702        final int pos = N*4;
703        history[pos] = mX;
704        history[pos+1] = mY;
705        history[pos+2] = mPressure;
706        history[pos+3] = mSize;
707        mNumHistory = N+1;
708
709        mEventTime = eventTime;
710        mX = mRawX = x;
711        mY = mRawY = y;
712        mPressure = pressure;
713        mSize = size;
714        mMetaState |= metaState;
715    }
716
717    @Override
718    public String toString() {
719        return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
720            + " action=" + mAction + " x=" + mX
721            + " y=" + mY + " pressure=" + mPressure + " size=" + mSize + "}";
722    }
723
724    public static final Parcelable.Creator<MotionEvent> CREATOR
725            = new Parcelable.Creator<MotionEvent>() {
726        public MotionEvent createFromParcel(Parcel in) {
727            MotionEvent ev = obtain();
728            ev.readFromParcel(in);
729            return ev;
730        }
731
732        public MotionEvent[] newArray(int size) {
733            return new MotionEvent[size];
734        }
735    };
736
737    public int describeContents() {
738        return 0;
739    }
740
741    public void writeToParcel(Parcel out, int flags) {
742        out.writeLong(mDownTime);
743        out.writeLong(mEventTime);
744        out.writeLong(mEventTimeNano);
745        out.writeInt(mAction);
746        out.writeFloat(mX);
747        out.writeFloat(mY);
748        out.writeFloat(mPressure);
749        out.writeFloat(mSize);
750        out.writeInt(mMetaState);
751        out.writeFloat(mRawX);
752        out.writeFloat(mRawY);
753        final int N = mNumHistory;
754        out.writeInt(N);
755        if (N > 0) {
756            final int N4 = N*4;
757            int i;
758            float[] history = mHistory;
759            for (i=0; i<N4; i++) {
760                out.writeFloat(history[i]);
761            }
762            long[] times = mHistoryTimes;
763            for (i=0; i<N; i++) {
764                out.writeLong(times[i]);
765            }
766        }
767        out.writeFloat(mXPrecision);
768        out.writeFloat(mYPrecision);
769        out.writeInt(mDeviceId);
770        out.writeInt(mEdgeFlags);
771    }
772
773    private void readFromParcel(Parcel in) {
774        mDownTime = in.readLong();
775        mEventTime = in.readLong();
776        mEventTimeNano = in.readLong();
777        mAction = in.readInt();
778        mX = in.readFloat();
779        mY = in.readFloat();
780        mPressure = in.readFloat();
781        mSize = in.readFloat();
782        mMetaState = in.readInt();
783        mRawX = in.readFloat();
784        mRawY = in.readFloat();
785        final int N = in.readInt();
786        if ((mNumHistory=N) > 0) {
787            final int N4 = N*4;
788            float[] history = mHistory;
789            if (history == null || history.length < N4) {
790                mHistory = history = new float[N4 + (4*4)];
791            }
792            for (int i=0; i<N4; i++) {
793                history[i] = in.readFloat();
794            }
795            long[] times = mHistoryTimes;
796            if (times == null || times.length < N) {
797                mHistoryTimes = times = new long[N + 4];
798            }
799            for (int i=0; i<N; i++) {
800                times[i] = in.readLong();
801            }
802        }
803        mXPrecision = in.readFloat();
804        mYPrecision = in.readFloat();
805        mDeviceId = in.readInt();
806        mEdgeFlags = in.readInt();
807    }
808
809}
810