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