MotionEvent.java revision b125dc5599468a09d82751cd76152071ae485afb
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.Log;
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    static final boolean DEBUG_POINTERS = false;
31
32    /**
33     * Bit mask of the parts of the action code that are the action itself.
34     */
35    public static final int ACTION_MASK             = 0xff;
36
37    /**
38     * Constant for {@link #getAction}: A pressed gesture has started, the
39     * motion contains the initial starting location.
40     */
41    public static final int ACTION_DOWN             = 0;
42
43    /**
44     * Constant for {@link #getAction}: A pressed gesture has finished, the
45     * motion contains the final release location as well as any intermediate
46     * points since the last down or move event.
47     */
48    public static final int ACTION_UP               = 1;
49
50    /**
51     * Constant for {@link #getAction}: A change has happened during a
52     * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
53     * The motion contains the most recent point, as well as any intermediate
54     * points since the last down or move event.
55     */
56    public static final int ACTION_MOVE             = 2;
57
58    /**
59     * Constant for {@link #getAction}: The current gesture has been aborted.
60     * You will not receive any more points in it.  You should treat this as
61     * an up event, but not perform any action that you normally would.
62     */
63    public static final int ACTION_CANCEL           = 3;
64
65    /**
66     * Constant for {@link #getAction}: A movement has happened outside of the
67     * normal bounds of the UI element.  This does not provide a full gesture,
68     * but only the initial location of the movement/touch.
69     */
70    public static final int ACTION_OUTSIDE          = 4;
71
72    /**
73     * A non-primary pointer has gone down.  The bits in
74     * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
75     */
76    public static final int ACTION_POINTER_DOWN     = 5;
77
78    /**
79     * A non-primary pointer has gone up.  The bits in
80     * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
81     */
82    public static final int ACTION_POINTER_UP       = 6;
83
84    /**
85     * Bits in the action code that represent a pointer index, used with
86     * {@link #ACTION_POINTER_DOWN} and {@link #ACTION_POINTER_UP}.  Shifting
87     * down by {@link #ACTION_POINTER_INDEX_SHIFT} provides the actual pointer
88     * index where the data for the pointer going up or down can be found; you can
89     * get its identifier with {@link #getPointerId(int)} and the actual
90     * data with {@link #getX(int)} etc.
91     */
92    public static final int ACTION_POINTER_INDEX_MASK  = 0xff00;
93
94    /**
95     * Bit shift for the action bits holding the pointer index as
96     * defined by {@link #ACTION_POINTER_INDEX_MASK}.
97     */
98    public static final int ACTION_POINTER_INDEX_SHIFT = 8;
99
100    /**
101     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
102     * data index associated with {@link #ACTION_POINTER_DOWN}.
103     */
104    @Deprecated
105    public static final int ACTION_POINTER_1_DOWN   = ACTION_POINTER_DOWN | 0x0000;
106
107    /**
108     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
109     * data index associated with {@link #ACTION_POINTER_DOWN}.
110     */
111    @Deprecated
112    public static final int ACTION_POINTER_2_DOWN   = ACTION_POINTER_DOWN | 0x0100;
113
114    /**
115     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
116     * data index associated with {@link #ACTION_POINTER_DOWN}.
117     */
118    @Deprecated
119    public static final int ACTION_POINTER_3_DOWN   = ACTION_POINTER_DOWN | 0x0200;
120
121    /**
122     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
123     * data index associated with {@link #ACTION_POINTER_UP}.
124     */
125    @Deprecated
126    public static final int ACTION_POINTER_1_UP     = ACTION_POINTER_UP | 0x0000;
127
128    /**
129     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
130     * data index associated with {@link #ACTION_POINTER_UP}.
131     */
132    @Deprecated
133    public static final int ACTION_POINTER_2_UP     = ACTION_POINTER_UP | 0x0100;
134
135    /**
136     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
137     * data index associated with {@link #ACTION_POINTER_UP}.
138     */
139    @Deprecated
140    public static final int ACTION_POINTER_3_UP     = ACTION_POINTER_UP | 0x0200;
141
142    /**
143     * @deprecated Renamed to {@link #ACTION_POINTER_INDEX_MASK} to match
144     * the actual data contained in these bits.
145     */
146    @Deprecated
147    public static final int ACTION_POINTER_ID_MASK  = 0xff00;
148
149    /**
150     * @deprecated Renamed to {@link #ACTION_POINTER_INDEX_SHIFT} to match
151     * the actual data contained in these bits.
152     */
153    @Deprecated
154    public static final int ACTION_POINTER_ID_SHIFT = 8;
155
156    private static final boolean TRACK_RECYCLED_LOCATION = false;
157
158    /**
159     * Flag indicating the motion event intersected the top edge of the screen.
160     */
161    public static final int EDGE_TOP = 0x00000001;
162
163    /**
164     * Flag indicating the motion event intersected the bottom edge of the screen.
165     */
166    public static final int EDGE_BOTTOM = 0x00000002;
167
168    /**
169     * Flag indicating the motion event intersected the left edge of the screen.
170     */
171    public static final int EDGE_LEFT = 0x00000004;
172
173    /**
174     * Flag indicating the motion event intersected the right edge of the screen.
175     */
176    public static final int EDGE_RIGHT = 0x00000008;
177
178    /**
179     * Offset for the sample's X coordinate.
180     * @hide
181     */
182    static public final int SAMPLE_X = 0;
183
184    /**
185     * Offset for the sample's Y coordinate.
186     * @hide
187     */
188    static public final int SAMPLE_Y = 1;
189
190    /**
191     * Offset for the sample's X coordinate.
192     * @hide
193     */
194    static public final int SAMPLE_PRESSURE = 2;
195
196    /**
197     * Offset for the sample's X coordinate.
198     * @hide
199     */
200    static public final int SAMPLE_SIZE = 3;
201
202    /**
203     * Number of data items for each sample.
204     * @hide
205     */
206    static public final int NUM_SAMPLE_DATA = 4;
207
208    /**
209     * Number of possible pointers.
210     * @hide
211     */
212    static public final int BASE_AVAIL_POINTERS = 5;
213
214    static private final int BASE_AVAIL_SAMPLES = 8;
215
216    static private final int MAX_RECYCLED = 10;
217    static private Object gRecyclerLock = new Object();
218    static private int gRecyclerUsed = 0;
219    static private MotionEvent gRecyclerTop = null;
220
221    private long mDownTime;
222    private long mEventTimeNano;
223    private int mAction;
224    private float mRawX;
225    private float mRawY;
226    private float mXPrecision;
227    private float mYPrecision;
228    private int mDeviceId;
229    private int mEdgeFlags;
230    private int mMetaState;
231
232    // Here is the actual event data.  Note that the order of the array
233    // is a little odd: the first entry is the most recent, and the ones
234    // following it are the historical data from oldest to newest.  This
235    // allows us to easily retrieve the most recent data, without having
236    // to copy the arrays every time a new sample is added.
237
238    private int mNumPointers;
239    private int mNumSamples;
240    // Array of mNumPointers size of identifiers for each pointer of data.
241    private int[] mPointerIdentifiers;
242    // Array of (mNumSamples * mNumPointers * NUM_SAMPLE_DATA) size of event data.
243    private float[] mDataSamples;
244    // Array of mNumSamples size of time stamps.
245    private long[] mTimeSamples;
246
247    private MotionEvent mNext;
248    private RuntimeException mRecycledLocation;
249    private boolean mRecycled;
250
251    private MotionEvent() {
252        mPointerIdentifiers = new int[BASE_AVAIL_POINTERS];
253        mDataSamples = new float[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES*NUM_SAMPLE_DATA];
254        mTimeSamples = new long[BASE_AVAIL_SAMPLES];
255    }
256
257    static private MotionEvent obtain() {
258        synchronized (gRecyclerLock) {
259            if (gRecyclerTop == null) {
260                return new MotionEvent();
261            }
262            MotionEvent ev = gRecyclerTop;
263            gRecyclerTop = ev.mNext;
264            gRecyclerUsed--;
265            ev.mRecycledLocation = null;
266            ev.mRecycled = false;
267            return ev;
268        }
269    }
270
271    /**
272     * Create a new MotionEvent, filling in all of the basic values that
273     * define the motion.
274     *
275     * @param downTime The time (in ms) when the user originally pressed down to start
276     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
277     * @param eventTime  The the time (in ms) when this specific event was generated.  This
278     * must be obtained from {@link SystemClock#uptimeMillis()}.
279     * @param eventTimeNano  The the time (in ns) when this specific event was generated.  This
280     * must be obtained from {@link System#nanoTime()}.
281     * @param action The kind of action being performed -- one of either
282     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
283     * {@link #ACTION_CANCEL}.
284     * @param pointers The number of points that will be in this event.
285     * @param inPointerIds An array of <em>pointers</em> values providing
286     * an identifier for each pointer.
287     * @param inData An array of <em>pointers*NUM_SAMPLE_DATA</em> of initial
288     * data samples for the event.
289     * @param metaState The state of any meta / modifier keys that were in effect when
290     * the event was generated.
291     * @param xPrecision The precision of the X coordinate being reported.
292     * @param yPrecision The precision of the Y coordinate being reported.
293     * @param deviceId The id for the device that this event came from.  An id of
294     * zero indicates that the event didn't come from a physical device; other
295     * numbers are arbitrary and you shouldn't depend on the values.
296     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
297     * MotionEvent.
298     *
299     * @hide
300     */
301    static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
302            int action, int pointers, int[] inPointerIds, float[] inData, int metaState,
303            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
304        MotionEvent ev = obtain();
305        ev.mDeviceId = deviceId;
306        ev.mEdgeFlags = edgeFlags;
307        ev.mDownTime = downTime;
308        ev.mEventTimeNano = eventTimeNano;
309        ev.mAction = action;
310        ev.mMetaState = metaState;
311        ev.mRawX = inData[SAMPLE_X];
312        ev.mRawY = inData[SAMPLE_Y];
313        ev.mXPrecision = xPrecision;
314        ev.mYPrecision = yPrecision;
315        ev.mNumPointers = pointers;
316        ev.mNumSamples = 1;
317
318        int[] pointerIdentifiers = ev.mPointerIdentifiers;
319        if (pointerIdentifiers.length < pointers) {
320            ev.mPointerIdentifiers = pointerIdentifiers = new int[pointers];
321        }
322        System.arraycopy(inPointerIds, 0, pointerIdentifiers, 0, pointers);
323
324        final int ND = pointers * NUM_SAMPLE_DATA;
325        float[] dataSamples = ev.mDataSamples;
326        if (dataSamples.length < ND) {
327            ev.mDataSamples = dataSamples = new float[ND];
328        }
329        System.arraycopy(inData, 0, dataSamples, 0, ND);
330
331        ev.mTimeSamples[0] = eventTime;
332
333        if (DEBUG_POINTERS) {
334            StringBuilder sb = new StringBuilder(128);
335            sb.append("New:");
336            for (int i=0; i<pointers; i++) {
337                sb.append(" #");
338                sb.append(ev.mPointerIdentifiers[i]);
339                sb.append("(");
340                sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
341                sb.append(",");
342                sb.append(ev.mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
343                sb.append(")");
344            }
345            Log.v("MotionEvent", sb.toString());
346        }
347
348        return ev;
349    }
350
351    /**
352     * Create a new MotionEvent, filling in all of the basic values that
353     * define the motion.
354     *
355     * @param downTime The time (in ms) when the user originally pressed down to start
356     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
357     * @param eventTime  The the time (in ms) when this specific event was generated.  This
358     * must be obtained from {@link SystemClock#uptimeMillis()}.
359     * @param action The kind of action being performed -- one of either
360     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
361     * {@link #ACTION_CANCEL}.
362     * @param x The X coordinate of this event.
363     * @param y The Y coordinate of this event.
364     * @param pressure The current pressure of this event.  The pressure generally
365     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
366     * values higher than 1 may be generated depending on the calibration of
367     * the input device.
368     * @param size A scaled value of the approximate size of the area being pressed when
369     * touched with the finger. The actual value in pixels corresponding to the finger
370     * touch is normalized with a device specific range of values
371     * and scaled to a value between 0 and 1.
372     * @param metaState The state of any meta / modifier keys that were in effect when
373     * the event was generated.
374     * @param xPrecision The precision of the X coordinate being reported.
375     * @param yPrecision The precision of the Y coordinate being reported.
376     * @param deviceId The id for the device that this event came from.  An id of
377     * zero indicates that the event didn't come from a physical device; other
378     * numbers are arbitrary and you shouldn't depend on the values.
379     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
380     * MotionEvent.
381     */
382    static public MotionEvent obtain(long downTime, long eventTime, int action,
383            float x, float y, float pressure, float size, int metaState,
384            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
385        MotionEvent ev = obtain();
386        ev.mDeviceId = deviceId;
387        ev.mEdgeFlags = edgeFlags;
388        ev.mDownTime = downTime;
389        ev.mEventTimeNano = eventTime * 1000000;
390        ev.mAction = action;
391        ev.mMetaState = metaState;
392        ev.mXPrecision = xPrecision;
393        ev.mYPrecision = yPrecision;
394
395        ev.mNumPointers = 1;
396        ev.mNumSamples = 1;
397        int[] pointerIds = ev.mPointerIdentifiers;
398        pointerIds[0] = 0;
399        float[] data = ev.mDataSamples;
400        data[SAMPLE_X] = ev.mRawX = x;
401        data[SAMPLE_Y] = ev.mRawY = y;
402        data[SAMPLE_PRESSURE] = pressure;
403        data[SAMPLE_SIZE] = size;
404        ev.mTimeSamples[0] = eventTime;
405
406        return ev;
407    }
408
409    /**
410     * Create a new MotionEvent, filling in all of the basic values that
411     * define the motion.
412     *
413     * @param downTime The time (in ms) when the user originally pressed down to start
414     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
415     * @param eventTime  The the time (in ms) when this specific event was generated.  This
416     * must be obtained from {@link SystemClock#uptimeMillis()}.
417     * @param action The kind of action being performed -- one of either
418     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
419     * {@link #ACTION_CANCEL}.
420     * @param pointers The number of pointers that are active in this event.
421     * @param x The X coordinate of this event.
422     * @param y The Y coordinate of this event.
423     * @param pressure The current pressure of this event.  The pressure generally
424     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
425     * values higher than 1 may be generated depending on the calibration of
426     * the input device.
427     * @param size A scaled value of the approximate size of the area being pressed when
428     * touched with the finger. The actual value in pixels corresponding to the finger
429     * touch is normalized with a device specific range of values
430     * and scaled to a value between 0 and 1.
431     * @param metaState The state of any meta / modifier keys that were in effect when
432     * the event was generated.
433     * @param xPrecision The precision of the X coordinate being reported.
434     * @param yPrecision The precision of the Y coordinate being reported.
435     * @param deviceId The id for the device that this event came from.  An id of
436     * zero indicates that the event didn't come from a physical device; other
437     * numbers are arbitrary and you shouldn't depend on the values.
438     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
439     * MotionEvent.
440     */
441    static public MotionEvent obtain(long downTime, long eventTime, int action,
442            int pointers, float x, float y, float pressure, float size, int metaState,
443            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
444        MotionEvent ev = obtain();
445        ev.mDeviceId = deviceId;
446        ev.mEdgeFlags = edgeFlags;
447        ev.mDownTime = downTime;
448        ev.mEventTimeNano = eventTime * 1000000;
449        ev.mAction = action;
450        ev.mNumPointers = pointers;
451        ev.mMetaState = metaState;
452        ev.mXPrecision = xPrecision;
453        ev.mYPrecision = yPrecision;
454
455        ev.mNumPointers = 1;
456        ev.mNumSamples = 1;
457        int[] pointerIds = ev.mPointerIdentifiers;
458        pointerIds[0] = 0;
459        float[] data = ev.mDataSamples;
460        data[SAMPLE_X] = ev.mRawX = x;
461        data[SAMPLE_Y] = ev.mRawY = y;
462        data[SAMPLE_PRESSURE] = pressure;
463        data[SAMPLE_SIZE] = size;
464        ev.mTimeSamples[0] = eventTime;
465
466        return ev;
467    }
468
469    /**
470     * Create a new MotionEvent, filling in a subset of the basic motion
471     * values.  Those not specified here are: device id (always 0), pressure
472     * and size (always 1), x and y precision (always 1), and edgeFlags (always 0).
473     *
474     * @param downTime The time (in ms) when the user originally pressed down to start
475     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
476     * @param eventTime  The the time (in ms) when this specific event was generated.  This
477     * must be obtained from {@link SystemClock#uptimeMillis()}.
478     * @param action The kind of action being performed -- one of either
479     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
480     * {@link #ACTION_CANCEL}.
481     * @param x The X coordinate of this event.
482     * @param y The Y coordinate of this event.
483     * @param metaState The state of any meta / modifier keys that were in effect when
484     * the event was generated.
485     */
486    static public MotionEvent obtain(long downTime, long eventTime, int action,
487            float x, float y, int metaState) {
488        MotionEvent ev = obtain();
489        ev.mDeviceId = 0;
490        ev.mEdgeFlags = 0;
491        ev.mDownTime = downTime;
492        ev.mEventTimeNano = eventTime * 1000000;
493        ev.mAction = action;
494        ev.mNumPointers = 1;
495        ev.mMetaState = metaState;
496        ev.mXPrecision = 1.0f;
497        ev.mYPrecision = 1.0f;
498
499        ev.mNumPointers = 1;
500        ev.mNumSamples = 1;
501        int[] pointerIds = ev.mPointerIdentifiers;
502        pointerIds[0] = 0;
503        float[] data = ev.mDataSamples;
504        data[SAMPLE_X] = ev.mRawX = x;
505        data[SAMPLE_Y] = ev.mRawY = y;
506        data[SAMPLE_PRESSURE] = 1.0f;
507        data[SAMPLE_SIZE] = 1.0f;
508        ev.mTimeSamples[0] = eventTime;
509
510        return ev;
511    }
512
513    /**
514     * Scales down the coordination of this event by the given scale.
515     *
516     * @hide
517     */
518    public void scale(float scale) {
519        mRawX *= scale;
520        mRawY *= scale;
521        mXPrecision *= scale;
522        mYPrecision *= scale;
523        float[] history = mDataSamples;
524        final int length = mNumPointers * mNumSamples * NUM_SAMPLE_DATA;
525        for (int i = 0; i < length; i += NUM_SAMPLE_DATA) {
526            history[i + SAMPLE_X] *= scale;
527            history[i + SAMPLE_Y] *= scale;
528            // no need to scale pressure
529            history[i + SAMPLE_SIZE] *= scale;    // TODO: square this?
530        }
531    }
532
533    /**
534     * Create a new MotionEvent, copying from an existing one.
535     */
536    static public MotionEvent obtain(MotionEvent o) {
537        MotionEvent ev = obtain();
538        ev.mDeviceId = o.mDeviceId;
539        ev.mEdgeFlags = o.mEdgeFlags;
540        ev.mDownTime = o.mDownTime;
541        ev.mEventTimeNano = o.mEventTimeNano;
542        ev.mAction = o.mAction;
543        ev.mNumPointers = o.mNumPointers;
544        ev.mRawX = o.mRawX;
545        ev.mRawY = o.mRawY;
546        ev.mMetaState = o.mMetaState;
547        ev.mXPrecision = o.mXPrecision;
548        ev.mYPrecision = o.mYPrecision;
549
550        final int NS = ev.mNumSamples = o.mNumSamples;
551        if (ev.mTimeSamples.length >= NS) {
552            System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NS);
553        } else {
554            ev.mTimeSamples = (long[])o.mTimeSamples.clone();
555        }
556
557        final int NP = (ev.mNumPointers=o.mNumPointers);
558        if (ev.mPointerIdentifiers.length >= NP) {
559            System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
560        } else {
561            ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
562        }
563
564        final int ND = NP * NS * NUM_SAMPLE_DATA;
565        if (ev.mDataSamples.length >= ND) {
566            System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
567        } else {
568            ev.mDataSamples = (float[])o.mDataSamples.clone();
569        }
570
571        return ev;
572    }
573
574    /**
575     * Create a new MotionEvent, copying from an existing one, but not including
576     * any historical point information.
577     */
578    static public MotionEvent obtainNoHistory(MotionEvent o) {
579        MotionEvent ev = obtain();
580        ev.mDeviceId = o.mDeviceId;
581        ev.mEdgeFlags = o.mEdgeFlags;
582        ev.mDownTime = o.mDownTime;
583        ev.mEventTimeNano = o.mEventTimeNano;
584        ev.mAction = o.mAction;
585        ev.mNumPointers = o.mNumPointers;
586        ev.mRawX = o.mRawX;
587        ev.mRawY = o.mRawY;
588        ev.mMetaState = o.mMetaState;
589        ev.mXPrecision = o.mXPrecision;
590        ev.mYPrecision = o.mYPrecision;
591
592        ev.mNumSamples = 1;
593        ev.mTimeSamples[0] = o.mTimeSamples[0];
594
595        final int NP = (ev.mNumPointers=o.mNumPointers);
596        if (ev.mPointerIdentifiers.length >= NP) {
597            System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
598        } else {
599            ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
600        }
601
602        final int ND = NP * NUM_SAMPLE_DATA;
603        if (ev.mDataSamples.length >= ND) {
604            System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
605        } else {
606            ev.mDataSamples = (float[])o.mDataSamples.clone();
607        }
608
609        return ev;
610    }
611
612    /**
613     * Recycle the MotionEvent, to be re-used by a later caller.  After calling
614     * this function you must not ever touch the event again.
615     */
616    public void recycle() {
617        // Ensure recycle is only called once!
618        if (TRACK_RECYCLED_LOCATION) {
619            if (mRecycledLocation != null) {
620                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
621            }
622            mRecycledLocation = new RuntimeException("Last recycled here");
623        } else if (mRecycled) {
624            throw new RuntimeException(toString() + " recycled twice!");
625        }
626
627        //Log.w("MotionEvent", "Recycling event " + this, mRecycledLocation);
628        synchronized (gRecyclerLock) {
629            if (gRecyclerUsed < MAX_RECYCLED) {
630                gRecyclerUsed++;
631                mNumSamples = 0;
632                mNext = gRecyclerTop;
633                gRecyclerTop = this;
634            }
635        }
636    }
637
638    /**
639     * Return the kind of action being performed -- one of either
640     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
641     * {@link #ACTION_CANCEL}.  Consider using {@link #getActionMasked}
642     * and {@link #getActionIndex} to retrieve the separate masked action
643     * and pointer index.
644     */
645    public final int getAction() {
646        return mAction;
647    }
648
649    /**
650     * Return the masked action being performed, without pointer index
651     * information.  May be any of the actions: {@link #ACTION_DOWN},
652     * {@link #ACTION_MOVE}, {@link #ACTION_UP}, {@link #ACTION_CANCEL},
653     * {@link #ACTION_POINTER_DOWN}, or {@link #ACTION_POINTER_UP}.
654     * Use {@link #getActionIndex} to return the index associated with
655     * pointer actions.
656     */
657    public final int getActionMasked() {
658        return mAction & ACTION_MASK;
659    }
660
661    /**
662     * For {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP}
663     * as returned by {@link #getActionMasked}, this returns the associated
664     * pointer index.  The index may be used with {@link #getPointerId(int)},
665     * {@link #getX(int)}, {@link #getY(int)}, {@link #getPressure(int)},
666     * and {@link #getSize(int)} to get information about the pointer that has
667     * gone down or up.
668     */
669    public final int getActionIndex() {
670        return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
671    }
672
673    /**
674     * Returns the time (in ms) when the user originally pressed down to start
675     * a stream of position events.
676     */
677    public final long getDownTime() {
678        return mDownTime;
679    }
680
681    /**
682     * Returns the time (in ms) when this specific event was generated.
683     */
684    public final long getEventTime() {
685        return mTimeSamples[0];
686    }
687
688    /**
689     * Returns the time (in ns) when this specific event was generated.
690     * The value is in nanosecond precision but it may not have nanosecond accuracy.
691     *
692     * @hide
693     */
694    public final long getEventTimeNano() {
695        return mEventTimeNano;
696    }
697
698    /**
699     * {@link #getX(int)} for the first pointer index (may be an
700     * arbitrary pointer identifier).
701     */
702    public final float getX() {
703        return mDataSamples[SAMPLE_X];
704    }
705
706    /**
707     * {@link #getY(int)} for the first pointer index (may be an
708     * arbitrary pointer identifier).
709     */
710    public final float getY() {
711        return mDataSamples[SAMPLE_Y];
712    }
713
714    /**
715     * {@link #getPressure(int)} for the first pointer index (may be an
716     * arbitrary pointer identifier).
717     */
718    public final float getPressure() {
719        return mDataSamples[SAMPLE_PRESSURE];
720    }
721
722    /**
723     * {@link #getSize(int)} for the first pointer index (may be an
724     * arbitrary pointer identifier).
725     */
726    public final float getSize() {
727        return mDataSamples[SAMPLE_SIZE];
728    }
729
730    /**
731     * The number of pointers of data contained in this event.  Always
732     * >= 1.
733     */
734    public final int getPointerCount() {
735        return mNumPointers;
736    }
737
738    /**
739     * Return the pointer identifier associated with a particular pointer
740     * data index is this event.  The identifier tells you the actual pointer
741     * number associated with the data, accounting for individual pointers
742     * going up and down since the start of the current gesture.
743     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
744     * (the first pointer that is down) to {@link #getPointerCount()}-1.
745     */
746    public final int getPointerId(int pointerIndex) {
747        return mPointerIdentifiers[pointerIndex];
748    }
749
750    /**
751     * Given a pointer identifier, find the index of its data in the event.
752     *
753     * @param pointerId The identifier of the pointer to be found.
754     * @return Returns either the index of the pointer (for use with
755     * {@link #getX(int) et al.), or -1 if there is no data available for
756     * that pointer identifier.
757     */
758    public final int findPointerIndex(int pointerId) {
759        int i = mNumPointers;
760        while (i > 0) {
761            i--;
762            if (mPointerIdentifiers[i] == pointerId) {
763                return i;
764            }
765        }
766        return -1;
767    }
768
769    /**
770     * Returns the X coordinate of this event for the given pointer
771     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
772     * identifier for this index).
773     * Whole numbers are pixels; the
774     * value may have a fraction for input devices that are sub-pixel precise.
775     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
776     * (the first pointer that is down) to {@link #getPointerCount()}-1.
777     */
778    public final float getX(int pointerIndex) {
779        return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_X];
780    }
781
782    /**
783     * Returns the Y coordinate of this event for the given pointer
784     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
785     * identifier for this index).
786     * Whole numbers are pixels; the
787     * value may have a fraction for input devices that are sub-pixel precise.
788     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
789     * (the first pointer that is down) to {@link #getPointerCount()}-1.
790     */
791    public final float getY(int pointerIndex) {
792        return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_Y];
793    }
794
795    /**
796     * Returns the current pressure of this event for the given pointer
797     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
798     * identifier for this index).
799     * The pressure generally
800     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
801     * values higher than 1 may be generated depending on the calibration of
802     * the input device.
803     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
804     * (the first pointer that is down) to {@link #getPointerCount()}-1.
805     */
806    public final float getPressure(int pointerIndex) {
807        return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
808    }
809
810    /**
811     * Returns a scaled value of the approximate size for the given pointer
812     * <em>index</em> (use {@link #getPointerId(int)} to find the pointer
813     * identifier for this index).
814     * This represents some approximation of the area of the screen being
815     * pressed; the actual value in pixels corresponding to the
816     * touch is normalized with the device specific range of values
817     * and scaled to a value between 0 and 1. The value of size can be used to
818     * determine fat touch events.
819     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
820     * (the first pointer that is down) to {@link #getPointerCount()}-1.
821     */
822    public final float getSize(int pointerIndex) {
823        return mDataSamples[(pointerIndex*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
824    }
825
826    /**
827     * Returns the state of any meta / modifier keys that were in effect when
828     * the event was generated.  This is the same values as those
829     * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}.
830     *
831     * @return an integer in which each bit set to 1 represents a pressed
832     *         meta key
833     *
834     * @see KeyEvent#getMetaState()
835     */
836    public final int getMetaState() {
837        return mMetaState;
838    }
839
840    /**
841     * Returns the original raw X coordinate of this event.  For touch
842     * events on the screen, this is the original location of the event
843     * on the screen, before it had been adjusted for the containing window
844     * and views.
845     */
846    public final float getRawX() {
847        return mRawX;
848    }
849
850    /**
851     * Returns the original raw Y coordinate of this event.  For touch
852     * events on the screen, this is the original location of the event
853     * on the screen, before it had been adjusted for the containing window
854     * and views.
855     */
856    public final float getRawY() {
857        return mRawY;
858    }
859
860    /**
861     * Return the precision of the X coordinates being reported.  You can
862     * multiple this number with {@link #getX} to find the actual hardware
863     * value of the X coordinate.
864     * @return Returns the precision of X coordinates being reported.
865     */
866    public final float getXPrecision() {
867        return mXPrecision;
868    }
869
870    /**
871     * Return the precision of the Y coordinates being reported.  You can
872     * multiple this number with {@link #getY} to find the actual hardware
873     * value of the Y coordinate.
874     * @return Returns the precision of Y coordinates being reported.
875     */
876    public final float getYPrecision() {
877        return mYPrecision;
878    }
879
880    /**
881     * Returns the number of historical points in this event.  These are
882     * movements that have occurred between this event and the previous event.
883     * This only applies to ACTION_MOVE events -- all other actions will have
884     * a size of 0.
885     *
886     * @return Returns the number of historical points in the event.
887     */
888    public final int getHistorySize() {
889        return mNumSamples - 1;
890    }
891
892    /**
893     * Returns the time that a historical movement occurred between this event
894     * and the previous event.  Only applies to ACTION_MOVE events.
895     *
896     * @param pos Which historical value to return; must be less than
897     * {@link #getHistorySize}
898     *
899     * @see #getHistorySize
900     * @see #getEventTime
901     */
902    public final long getHistoricalEventTime(int pos) {
903        return mTimeSamples[pos + 1];
904    }
905
906    /**
907     * {@link #getHistoricalX(int)} for the first pointer index (may be an
908     * arbitrary pointer identifier).
909     */
910    public final float getHistoricalX(int pos) {
911        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_X];
912    }
913
914    /**
915     * {@link #getHistoricalY(int)} for the first pointer index (may be an
916     * arbitrary pointer identifier).
917     */
918    public final float getHistoricalY(int pos) {
919        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_Y];
920    }
921
922    /**
923     * {@link #getHistoricalPressure(int)} for the first pointer index (may be an
924     * arbitrary pointer identifier).
925     */
926    public final float getHistoricalPressure(int pos) {
927        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_PRESSURE];
928    }
929
930    /**
931     * {@link #getHistoricalSize(int)} for the first pointer index (may be an
932     * arbitrary pointer identifier).
933     */
934    public final float getHistoricalSize(int pos) {
935        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_SIZE];
936    }
937
938    /**
939     * Returns a historical X coordinate, as per {@link #getX(int)}, that
940     * occurred between this event and the previous event for the given pointer.
941     * Only applies to ACTION_MOVE events.
942     *
943     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
944     * (the first pointer that is down) to {@link #getPointerCount()}-1.
945     * @param pos Which historical value to return; must be less than
946     * {@link #getHistorySize}
947     *
948     * @see #getHistorySize
949     * @see #getX
950     */
951    public final float getHistoricalX(int pointerIndex, int pos) {
952        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
953                            + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_X];
954    }
955
956    /**
957     * Returns a historical Y coordinate, as per {@link #getY(int)}, that
958     * occurred between this event and the previous event for the given pointer.
959     * Only applies to ACTION_MOVE events.
960     *
961     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
962     * (the first pointer that is down) to {@link #getPointerCount()}-1.
963     * @param pos Which historical value to return; must be less than
964     * {@link #getHistorySize}
965     *
966     * @see #getHistorySize
967     * @see #getY
968     */
969    public final float getHistoricalY(int pointerIndex, int pos) {
970        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
971                            + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_Y];
972    }
973
974    /**
975     * Returns a historical pressure coordinate, as per {@link #getPressure(int)},
976     * that occurred between this event and the previous event for the given
977     * pointer.  Only applies to ACTION_MOVE events.
978     *
979     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
980     * (the first pointer that is down) to {@link #getPointerCount()}-1.
981     * @param pos Which historical value to return; must be less than
982     * {@link #getHistorySize}
983     *
984     * @see #getHistorySize
985     * @see #getPressure
986     */
987    public final float getHistoricalPressure(int pointerIndex, int pos) {
988        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
989                            + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
990    }
991
992    /**
993     * Returns a historical size coordinate, as per {@link #getSize(int)}, that
994     * occurred between this event and the previous event for the given pointer.
995     * Only applies to ACTION_MOVE events.
996     *
997     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
998     * (the first pointer that is down) to {@link #getPointerCount()}-1.
999     * @param pos Which historical value to return; must be less than
1000     * {@link #getHistorySize}
1001     *
1002     * @see #getHistorySize
1003     * @see #getSize
1004     */
1005    public final float getHistoricalSize(int pointerIndex, int pos) {
1006        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
1007                            + (pointerIndex * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
1008    }
1009
1010    /**
1011     * Return the id for the device that this event came from.  An id of
1012     * zero indicates that the event didn't come from a physical device; other
1013     * numbers are arbitrary and you shouldn't depend on the values.
1014     */
1015    public final int getDeviceId() {
1016        return mDeviceId;
1017    }
1018
1019    /**
1020     * Returns a bitfield indicating which edges, if any, where touched by this
1021     * MotionEvent. For touch events, clients can use this to determine if the
1022     * user's finger was touching the edge of the display.
1023     *
1024     * @see #EDGE_LEFT
1025     * @see #EDGE_TOP
1026     * @see #EDGE_RIGHT
1027     * @see #EDGE_BOTTOM
1028     */
1029    public final int getEdgeFlags() {
1030        return mEdgeFlags;
1031    }
1032
1033
1034    /**
1035     * Sets the bitfield indicating which edges, if any, where touched by this
1036     * MotionEvent.
1037     *
1038     * @see #getEdgeFlags()
1039     */
1040    public final void setEdgeFlags(int flags) {
1041        mEdgeFlags = flags;
1042    }
1043
1044    /**
1045     * Sets this event's action.
1046     */
1047    public final void setAction(int action) {
1048        mAction = action;
1049    }
1050
1051    /**
1052     * Adjust this event's location.
1053     * @param deltaX Amount to add to the current X coordinate of the event.
1054     * @param deltaY Amount to add to the current Y coordinate of the event.
1055     */
1056    public final void offsetLocation(float deltaX, float deltaY) {
1057        final int N = mNumPointers*mNumSamples*4;
1058        final float[] pos = mDataSamples;
1059        for (int i=0; i<N; i+=NUM_SAMPLE_DATA) {
1060            pos[i+SAMPLE_X] += deltaX;
1061            pos[i+SAMPLE_Y] += deltaY;
1062        }
1063    }
1064
1065    /**
1066     * Set this event's location.  Applies {@link #offsetLocation} with a
1067     * delta from the current location to the given new location.
1068     *
1069     * @param x New absolute X location.
1070     * @param y New absolute Y location.
1071     */
1072    public final void setLocation(float x, float y) {
1073        float deltaX = x-mDataSamples[SAMPLE_X];
1074        float deltaY = y-mDataSamples[SAMPLE_Y];
1075        if (deltaX != 0 || deltaY != 0) {
1076            offsetLocation(deltaX, deltaY);
1077        }
1078    }
1079
1080    /**
1081     * Add a new movement to the batch of movements in this event.  The event's
1082     * current location, position and size is updated to the new values.  In
1083     * the future, the current values in the event will be added to a list of
1084     * historic values.
1085     *
1086     * @param eventTime The time stamp for this data.
1087     * @param x The new X position.
1088     * @param y The new Y position.
1089     * @param pressure The new pressure.
1090     * @param size The new size.
1091     * @param metaState Meta key state.
1092     */
1093    public final void addBatch(long eventTime, float x, float y,
1094            float pressure, float size, int metaState) {
1095        float[] data = mDataSamples;
1096        long[] times = mTimeSamples;
1097
1098        final int NP = mNumPointers;
1099        final int NS = mNumSamples;
1100        final int NI = NP*NS;
1101        final int ND = NI * NUM_SAMPLE_DATA;
1102        if (data.length <= ND) {
1103            final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
1104            float[] newData = new float[NEW_ND];
1105            System.arraycopy(data, 0, newData, 0, ND);
1106            mDataSamples = data = newData;
1107        }
1108        if (times.length <= NS) {
1109            final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
1110            long[] newHistoryTimes = new long[NEW_NS];
1111            System.arraycopy(times, 0, newHistoryTimes, 0, NS);
1112            mTimeSamples = times = newHistoryTimes;
1113        }
1114
1115        times[NS] = times[0];
1116        times[0] = eventTime;
1117
1118        final int pos = NS*NUM_SAMPLE_DATA;
1119        data[pos+SAMPLE_X] = data[SAMPLE_X];
1120        data[pos+SAMPLE_Y] = data[SAMPLE_Y];
1121        data[pos+SAMPLE_PRESSURE] = data[SAMPLE_PRESSURE];
1122        data[pos+SAMPLE_SIZE] = data[SAMPLE_SIZE];
1123        data[SAMPLE_X] = x;
1124        data[SAMPLE_Y] = y;
1125        data[SAMPLE_PRESSURE] = pressure;
1126        data[SAMPLE_SIZE] = size;
1127        mNumSamples = NS+1;
1128
1129        mRawX = x;
1130        mRawY = y;
1131        mMetaState |= metaState;
1132    }
1133
1134    /**
1135     * Add a new movement to the batch of movements in this event.  The
1136     * input data must contain (NUM_SAMPLE_DATA * {@link #getPointerCount()})
1137     * samples of data.
1138     *
1139     * @param eventTime The time stamp for this data.
1140     * @param inData The actual data.
1141     * @param metaState Meta key state.
1142     *
1143     * @hide
1144     */
1145    public final void addBatch(long eventTime, float[] inData, int metaState) {
1146        float[] data = mDataSamples;
1147        long[] times = mTimeSamples;
1148
1149        final int NP = mNumPointers;
1150        final int NS = mNumSamples;
1151        final int NI = NP*NS;
1152        final int ND = NI * NUM_SAMPLE_DATA;
1153        if (data.length < (ND+(NP*NUM_SAMPLE_DATA))) {
1154            final int NEW_ND = ND + (NP * (BASE_AVAIL_SAMPLES * NUM_SAMPLE_DATA));
1155            float[] newData = new float[NEW_ND];
1156            System.arraycopy(data, 0, newData, 0, ND);
1157            mDataSamples = data = newData;
1158        }
1159        if (times.length < (NS+1)) {
1160            final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
1161            long[] newHistoryTimes = new long[NEW_NS];
1162            System.arraycopy(times, 0, newHistoryTimes, 0, NS);
1163            mTimeSamples = times = newHistoryTimes;
1164        }
1165
1166        times[NS] = times[0];
1167        times[0] = eventTime;
1168
1169        System.arraycopy(data, 0, data, ND, mNumPointers*NUM_SAMPLE_DATA);
1170        System.arraycopy(inData, 0, data, 0, mNumPointers*NUM_SAMPLE_DATA);
1171
1172        mNumSamples = NS+1;
1173
1174        mRawX = inData[SAMPLE_X];
1175        mRawY = inData[SAMPLE_Y];
1176        mMetaState |= metaState;
1177
1178        if (DEBUG_POINTERS) {
1179            StringBuilder sb = new StringBuilder(128);
1180            sb.append("Add:");
1181            for (int i=0; i<mNumPointers; i++) {
1182                sb.append(" #");
1183                sb.append(mPointerIdentifiers[i]);
1184                sb.append("(");
1185                sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_X]);
1186                sb.append(",");
1187                sb.append(mDataSamples[(i*NUM_SAMPLE_DATA) + SAMPLE_Y]);
1188                sb.append(")");
1189            }
1190            Log.v("MotionEvent", sb.toString());
1191        }
1192    }
1193
1194    @Override
1195    public String toString() {
1196        return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
1197            + " action=" + mAction + " x=" + getX()
1198            + " y=" + getY() + " pressure=" + getPressure() + " size=" + getSize() + "}";
1199    }
1200
1201    public static final Parcelable.Creator<MotionEvent> CREATOR
1202            = new Parcelable.Creator<MotionEvent>() {
1203        public MotionEvent createFromParcel(Parcel in) {
1204            MotionEvent ev = obtain();
1205            ev.readFromParcel(in);
1206            return ev;
1207        }
1208
1209        public MotionEvent[] newArray(int size) {
1210            return new MotionEvent[size];
1211        }
1212    };
1213
1214    public int describeContents() {
1215        return 0;
1216    }
1217
1218    public void writeToParcel(Parcel out, int flags) {
1219        out.writeLong(mDownTime);
1220        out.writeLong(mEventTimeNano);
1221        out.writeInt(mAction);
1222        out.writeInt(mMetaState);
1223        out.writeFloat(mRawX);
1224        out.writeFloat(mRawY);
1225        final int NP = mNumPointers;
1226        out.writeInt(NP);
1227        final int NS = mNumSamples;
1228        out.writeInt(NS);
1229        final int NI = NP*NS;
1230        if (NI > 0) {
1231            int i;
1232            int[] state = mPointerIdentifiers;
1233            for (i=0; i<NP; i++) {
1234                out.writeInt(state[i]);
1235            }
1236            final int ND = NI*NUM_SAMPLE_DATA;
1237            float[] history = mDataSamples;
1238            for (i=0; i<ND; i++) {
1239                out.writeFloat(history[i]);
1240            }
1241            long[] times = mTimeSamples;
1242            for (i=0; i<NS; i++) {
1243                out.writeLong(times[i]);
1244            }
1245        }
1246        out.writeFloat(mXPrecision);
1247        out.writeFloat(mYPrecision);
1248        out.writeInt(mDeviceId);
1249        out.writeInt(mEdgeFlags);
1250    }
1251
1252    private void readFromParcel(Parcel in) {
1253        mDownTime = in.readLong();
1254        mEventTimeNano = in.readLong();
1255        mAction = in.readInt();
1256        mMetaState = in.readInt();
1257        mRawX = in.readFloat();
1258        mRawY = in.readFloat();
1259        final int NP = in.readInt();
1260        mNumPointers = NP;
1261        final int NS = in.readInt();
1262        mNumSamples = NS;
1263        final int NI = NP*NS;
1264        if (NI > 0) {
1265            int[] ids = mPointerIdentifiers;
1266            if (ids.length < NP) {
1267                mPointerIdentifiers = ids = new int[NP];
1268            }
1269            for (int i=0; i<NP; i++) {
1270                ids[i] = in.readInt();
1271            }
1272            float[] history = mDataSamples;
1273            final int ND = NI*NUM_SAMPLE_DATA;
1274            if (history.length < ND) {
1275                mDataSamples = history = new float[ND];
1276            }
1277            for (int i=0; i<ND; i++) {
1278                history[i] = in.readFloat();
1279            }
1280            long[] times = mTimeSamples;
1281            if (times == null || times.length < NS) {
1282                mTimeSamples = times = new long[NS];
1283            }
1284            for (int i=0; i<NS; i++) {
1285                times[i] = in.readLong();
1286            }
1287        }
1288        mXPrecision = in.readFloat();
1289        mYPrecision = in.readFloat();
1290        mDeviceId = in.readInt();
1291        mEdgeFlags = in.readInt();
1292    }
1293
1294}
1295