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