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