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