1 /* 2 * Copyright (C) 2010 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.compat.annotation.UnsupportedAppUsage; 20 import android.content.ClipData; 21 import android.content.ClipDescription; 22 import android.os.Build; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import com.android.internal.view.IDragAndDropPermissions; 27 28 //TODO: Improve Javadoc 29 /** 30 * Represents an event that is sent out by the system at various times during a drag and drop 31 * operation. It is a data structure that contains several important pieces of data about 32 * the operation and the underlying data. 33 * <p> 34 * View objects that receive a DragEvent call {@link #getAction()}, which returns 35 * an action type that indicates the state of the drag and drop operation. This allows a View 36 * object to react to a change in state by changing its appearance or performing other actions. 37 * For example, a View can react to the {@link #ACTION_DRAG_ENTERED} action type by 38 * by changing one or more colors in its displayed image. 39 * </p> 40 * <p> 41 * During a drag and drop operation, the system displays an image that the user drags. This image 42 * is called a drag shadow. Several action types reflect the position of the drag shadow relative 43 * to the View receiving the event. 44 * </p> 45 * <p> 46 * Most methods return valid data only for certain event actions. This is summarized in the 47 * following table. Each possible {@link #getAction()} value is listed in the first column. The 48 * other columns indicate which method or methods return valid data for that getAction() value: 49 * </p> 50 * <table> 51 * <tr> 52 * <th scope="col">getAction() Value</th> 53 * <th scope="col">getClipDescription()</th> 54 * <th scope="col">getLocalState()</th> 55 * <th scope="col">getX()</th> 56 * <th scope="col">getY()</th> 57 * <th scope="col">getClipData()</th> 58 * <th scope="col">getResult()</th> 59 * </tr> 60 * <tr> 61 * <td>ACTION_DRAG_STARTED</td> 62 * <td style="text-align: center;">X</td> 63 * <td style="text-align: center;">X</td> 64 * <td style="text-align: center;">X</td> 65 * <td style="text-align: center;">X</td> 66 * <td style="text-align: center;"> </td> 67 * <td style="text-align: center;"> </td> 68 * </tr> 69 * <tr> 70 * <td>ACTION_DRAG_ENTERED</td> 71 * <td style="text-align: center;">X</td> 72 * <td style="text-align: center;">X</td> 73 * <td style="text-align: center;"> </td> 74 * <td style="text-align: center;"> </td> 75 * <td style="text-align: center;"> </td> 76 * <td style="text-align: center;"> </td> 77 * </tr> 78 * <tr> 79 * <td>ACTION_DRAG_LOCATION</td> 80 * <td style="text-align: center;">X</td> 81 * <td style="text-align: center;">X</td> 82 * <td style="text-align: center;">X</td> 83 * <td style="text-align: center;">X</td> 84 * <td style="text-align: center;"> </td> 85 * <td style="text-align: center;"> </td> 86 * </tr> 87 * <tr> 88 * <td>ACTION_DRAG_EXITED</td> 89 * <td style="text-align: center;">X</td> 90 * <td style="text-align: center;">X</td> 91 * <td style="text-align: center;"> </td> 92 * <td style="text-align: center;"> </td> 93 * <td style="text-align: center;"> </td> 94 * <td style="text-align: center;"> </td> 95 * </tr> 96 * <tr> 97 * <td>ACTION_DROP</td> 98 * <td style="text-align: center;">X</td> 99 * <td style="text-align: center;">X</td> 100 * <td style="text-align: center;">X</td> 101 * <td style="text-align: center;">X</td> 102 * <td style="text-align: center;">X</td> 103 * <td style="text-align: center;"> </td> 104 * </tr> 105 * <tr> 106 * <td>ACTION_DRAG_ENDED</td> 107 * <td style="text-align: center;"> </td> 108 * <td style="text-align: center;">X</td> 109 * <td style="text-align: center;"> </td> 110 * <td style="text-align: center;"> </td> 111 * <td style="text-align: center;"> </td> 112 * <td style="text-align: center;">X</td> 113 * </tr> 114 * </table> 115 * <p> 116 * The {@link android.view.DragEvent#getAction()}, 117 * {@link android.view.DragEvent#getLocalState()} 118 * {@link android.view.DragEvent#describeContents()}, 119 * {@link android.view.DragEvent#writeToParcel(Parcel,int)}, and 120 * {@link android.view.DragEvent#toString()} methods always return valid data. 121 * </p> 122 * 123 * <div class="special reference"> 124 * <h3>Developer Guides</h3> 125 * <p>For a guide to implementing drag and drop features, read the 126 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 127 * </div> 128 */ 129 public class DragEvent implements Parcelable { 130 private static final boolean TRACK_RECYCLED_LOCATION = false; 131 132 int mAction; 133 float mX, mY; 134 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 135 ClipDescription mClipDescription; 136 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 137 ClipData mClipData; 138 IDragAndDropPermissions mDragAndDropPermissions; 139 140 Object mLocalState; 141 boolean mDragResult; 142 boolean mEventHandlerWasCalled; 143 144 /** 145 * The drag surface containing the object being dragged. Only provided if the target window 146 * has the {@link WindowManager.LayoutParams#PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP} flag 147 * and is only sent with {@link #ACTION_DROP}. 148 */ 149 private SurfaceControl mDragSurface; 150 151 /** 152 * The offsets from the touch that the surface is adjusted by as the surface is moved around the 153 * screen. Necessary for the target using the drag surface to animate it properly once it takes 154 * ownership of the drag surface after the drop. 155 */ 156 private float mOffsetX; 157 private float mOffsetY; 158 159 /** 160 * The id of the display where the `mX` and `mY` of this event belongs to. 161 */ 162 private int mDisplayId; 163 164 /** 165 * The View#DRAG_FLAG_* flags used to start the current drag, only provided if the target window 166 * has the {@link WindowManager.LayoutParams#PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP} flag 167 * and is only sent with {@link #ACTION_DRAG_STARTED} and {@link #ACTION_DROP}. 168 */ 169 private int mFlags; 170 171 private DragEvent mNext; 172 private RuntimeException mRecycledLocation; 173 private boolean mRecycled; 174 175 private static final int MAX_RECYCLED = 10; 176 private static final Object gRecyclerLock = new Object(); 177 private static int gRecyclerUsed = 0; 178 private static DragEvent gRecyclerTop = null; 179 180 /** 181 * Action constant returned by {@link #getAction()}: Signals the start of a 182 * drag and drop operation. The View should return {@code true} from its 183 * {@link View#onDragEvent(DragEvent) onDragEvent()} handler method or 184 * {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} listener 185 * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata 186 * from {@link #getClipDescription()} to determine if they can accept the data contained in 187 * this drag. For an operation that doesn't represent data transfer, these methods may 188 * perform other actions to determine whether or not the View should accept the data. 189 * If the View wants to indicate that it is a valid drop target, it can also react by 190 * changing its appearance. 191 * <p> 192 * Views added or becoming visible for the first time during a drag operation receive this 193 * event when they are added or becoming visible. 194 * </p> 195 * <p> 196 * A View only receives further drag events for the drag operation if it returns {@code true} 197 * in response to ACTION_DRAG_STARTED. 198 * </p> 199 * @see #ACTION_DRAG_ENDED 200 * @see #getX() 201 * @see #getY() 202 */ 203 public static final int ACTION_DRAG_STARTED = 1; 204 205 /** 206 * Action constant returned by {@link #getAction()}: Sent to a View after 207 * {@link #ACTION_DRAG_ENTERED} while the drag shadow is still within the View object's bounding 208 * box, but not within a descendant view that can accept the data. The {@link #getX()} and 209 * {@link #getY()} methods supply 210 * the X and Y position of the drag point within the View object's bounding box. 211 * <p> 212 * A View receives an {@link #ACTION_DRAG_ENTERED} event before receiving any 213 * ACTION_DRAG_LOCATION events. 214 * </p> 215 * <p> 216 * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the 217 * drag shadow out of the View object's bounding box or into a descendant view that can accept 218 * the data. If the user moves the drag shadow back into the View object's bounding box or out 219 * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again 220 * before receiving any more ACTION_DRAG_LOCATION events. 221 * </p> 222 * @see #ACTION_DRAG_ENTERED 223 * @see #getX() 224 * @see #getY() 225 */ 226 public static final int ACTION_DRAG_LOCATION = 2; 227 228 /** 229 * Action constant returned by {@link #getAction()}: Signals to a View that the user 230 * has released the drag shadow, and the drag point is within the bounding box of the View and 231 * not within a descendant view that can accept the data. 232 * The View should retrieve the data from the DragEvent by calling {@link #getClipData()}. 233 * The methods {@link #getX()} and {@link #getY()} return the X and Y position of the drop point 234 * within the View object's bounding box. 235 * <p> 236 * The View should return {@code true} from its {@link View#onDragEvent(DragEvent)} 237 * handler or {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} 238 * listener if it accepted the drop, and {@code false} if it ignored the drop. 239 * </p> 240 * <p> 241 * The View can also react to this action by changing its appearance. 242 * </p> 243 * @see #getClipData() 244 * @see #getX() 245 * @see #getY() 246 */ 247 public static final int ACTION_DROP = 3; 248 249 /** 250 * Action constant returned by {@link #getAction()}: Signals to a View that the drag and drop 251 * operation has concluded. A View that changed its appearance during the operation should 252 * return to its usual drawing state in response to this event. 253 * <p> 254 * All views with listeners that returned boolean <code>true</code> for the ACTION_DRAG_STARTED 255 * event will receive the ACTION_DRAG_ENDED event even if they are not currently visible when 256 * the drag ends. Views removed during the drag operation won't receive the ACTION_DRAG_ENDED 257 * event. 258 * </p> 259 * <p> 260 * The View object can call {@link #getResult()} to see the result of the operation. 261 * If a View returned {@code true} in response to {@link #ACTION_DROP}, then 262 * getResult() returns {@code true}, otherwise it returns {@code false}. 263 * </p> 264 * @see #ACTION_DRAG_STARTED 265 * @see #getResult() 266 */ 267 public static final int ACTION_DRAG_ENDED = 4; 268 269 /** 270 * Action constant returned by {@link #getAction()}: Signals to a View that the drag point has 271 * entered the bounding box of the View. 272 * <p> 273 * If the View can accept a drop, it can react to ACTION_DRAG_ENTERED 274 * by changing its appearance in a way that tells the user that the View is the current 275 * drop target. 276 * </p> 277 * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the 278 * drag shadow out of the View object's bounding box or into a descendant view that can accept 279 * the data. If the user moves the drag shadow back into the View object's bounding box or out 280 * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again 281 * before receiving any more ACTION_DRAG_LOCATION events. 282 * </p> 283 * @see #ACTION_DRAG_ENTERED 284 * @see #ACTION_DRAG_LOCATION 285 */ 286 public static final int ACTION_DRAG_ENTERED = 5; 287 288 /** 289 * Action constant returned by {@link #getAction()}: Signals that the user has moved the 290 * drag shadow out of the bounding box of the View or into a descendant view that can accept 291 * the data. 292 * The View can react by changing its appearance in a way that tells the user that 293 * View is no longer the immediate drop target. 294 * <p> 295 * After the system sends an ACTION_DRAG_EXITED event to the View, the View receives no more 296 * ACTION_DRAG_LOCATION events until the user drags the drag shadow back over the View. 297 * </p> 298 * 299 */ 300 public static final int ACTION_DRAG_EXITED = 6; 301 DragEvent()302 private DragEvent() { 303 } 304 init(int action, float x, float y, float offsetX, float offsetY, int displayId, int flags, ClipDescription description, ClipData data, SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result)305 private void init(int action, float x, float y, float offsetX, float offsetY, int displayId, 306 int flags, ClipDescription description, ClipData data, SurfaceControl dragSurface, 307 IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result) { 308 mAction = action; 309 mX = x; 310 mY = y; 311 mOffsetX = offsetX; 312 mOffsetY = offsetY; 313 mDisplayId = displayId; 314 mFlags = flags; 315 mClipDescription = description; 316 mClipData = data; 317 mDragSurface = dragSurface; 318 mDragAndDropPermissions = dragAndDropPermissions; 319 mLocalState = localState; 320 mDragResult = result; 321 } 322 obtain()323 static DragEvent obtain() { 324 return DragEvent.obtain(0, 0f, 0f, 0f, 0f, 0, 0, null, null, null, null, null, false); 325 } 326 327 /** @hide */ obtain(int action, float x, float y, float offsetX, float offsetY, int displayId, int flags, Object localState, ClipDescription description, ClipData data, SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, boolean result)328 public static DragEvent obtain(int action, float x, float y, float offsetX, float offsetY, 329 int displayId, int flags, Object localState, ClipDescription description, ClipData data, 330 SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, 331 boolean result) { 332 final DragEvent ev; 333 synchronized (gRecyclerLock) { 334 if (gRecyclerTop == null) { 335 ev = new DragEvent(); 336 ev.init(action, x, y, offsetX, offsetY, displayId, flags, description, data, 337 dragSurface, dragAndDropPermissions, localState, result); 338 return ev; 339 } 340 ev = gRecyclerTop; 341 gRecyclerTop = ev.mNext; 342 gRecyclerUsed -= 1; 343 } 344 ev.mRecycledLocation = null; 345 ev.mRecycled = false; 346 ev.mNext = null; 347 348 ev.init(action, x, y, offsetX, offsetY, displayId, flags, description, data, dragSurface, 349 dragAndDropPermissions, localState, result); 350 351 return ev; 352 } 353 354 /** @hide */ 355 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) obtain(DragEvent source)356 public static DragEvent obtain(DragEvent source) { 357 return obtain(source.mAction, source.mX, source.mY, source.mOffsetX, source.mOffsetY, 358 source.mDisplayId, source.mFlags, source.mLocalState, source.mClipDescription, 359 source.mClipData, source.mDragSurface, source.mDragAndDropPermissions, 360 source.mDragResult); 361 } 362 363 /** 364 * Inspect the action value of this event. 365 * @return One of the following action constants, in the order in which they usually occur 366 * during a drag and drop operation: 367 * <ul> 368 * <li>{@link #ACTION_DRAG_STARTED}</li> 369 * <li>{@link #ACTION_DRAG_ENTERED}</li> 370 * <li>{@link #ACTION_DRAG_LOCATION}</li> 371 * <li>{@link #ACTION_DROP}</li> 372 * <li>{@link #ACTION_DRAG_EXITED}</li> 373 * <li>{@link #ACTION_DRAG_ENDED}</li> 374 * </ul> 375 */ getAction()376 public int getAction() { 377 return mAction; 378 } 379 380 /** 381 * Gets the X coordinate of the drag point. The value is only valid if the event action is 382 * {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_LOCATION} or {@link #ACTION_DROP}. 383 * @return The current drag point's X coordinate 384 */ getX()385 public float getX() { 386 return mX; 387 } 388 389 /** 390 * Gets the Y coordinate of the drag point. The value is only valid if the event action is 391 * {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_LOCATION} or {@link #ACTION_DROP}. 392 * @return The current drag point's Y coordinate 393 */ getY()394 public float getY() { 395 return mY; 396 } 397 398 /** @hide */ getOffsetX()399 public float getOffsetX() { 400 return mOffsetX; 401 } 402 403 /** @hide */ getOffsetY()404 public float getOffsetY() { 405 return mOffsetY; 406 } 407 408 /** @hide */ getDisplayId()409 public int getDisplayId() { 410 return mDisplayId; 411 } 412 413 /** 414 * Returns the {@link android.content.ClipData} object sent to the system as part of the call 415 * to 416 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 417 * startDragAndDrop()}. 418 * This method only returns valid data if the event action is {@link #ACTION_DROP}. 419 * @return The ClipData sent to the system by startDragAndDrop(). 420 */ getClipData()421 public ClipData getClipData() { 422 return mClipData; 423 } 424 425 /** 426 * Returns the {@link android.content.ClipDescription} object contained in the 427 * {@link android.content.ClipData} object sent to the system as part of the call to 428 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 429 * startDragAndDrop()}. 430 * The drag handler or listener for a View can use the metadata in this object to decide if the 431 * View can accept the dragged View object's data. 432 * <p> 433 * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}. 434 * @return The ClipDescription that was part of the ClipData sent to the system by 435 * startDragAndDrop(). 436 */ getClipDescription()437 public ClipDescription getClipDescription() { 438 return mClipDescription; 439 } 440 441 /** @hide */ getDragSurface()442 public SurfaceControl getDragSurface() { 443 return mDragSurface; 444 } 445 446 /** @hide */ getDragFlags()447 public int getDragFlags() { 448 return mFlags; 449 } 450 451 /** @hide */ getDragAndDropPermissions()452 public IDragAndDropPermissions getDragAndDropPermissions() { 453 return mDragAndDropPermissions; 454 } 455 456 /** 457 * Returns the local state object sent to the system as part of the call to 458 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 459 * startDragAndDrop()}. 460 * The object is intended to provide local information about the drag and drop operation. For 461 * example, it can indicate whether the drag and drop operation is a copy or a move. 462 * <p> 463 * The local state is available only to views in the activity which has started the drag 464 * operation. In all other activities this method will return null 465 * </p> 466 * <p> 467 * This method returns valid data for all event actions. 468 * </p> 469 * @return The local state object sent to the system by startDragAndDrop(). 470 */ getLocalState()471 public Object getLocalState() { 472 return mLocalState; 473 } 474 475 /** 476 * <p> 477 * Returns an indication of the result of the drag and drop operation. 478 * This method only returns valid data if the action type is {@link #ACTION_DRAG_ENDED}. 479 * The return value depends on what happens after the user releases the drag shadow. 480 * </p> 481 * <p> 482 * If the user releases the drag shadow on a View that can accept a drop, the system sends an 483 * {@link #ACTION_DROP} event to the View object's drag event listener. If the listener 484 * returns {@code true}, then getResult() will return {@code true}. 485 * If the listener returns {@code false}, then getResult() returns {@code false}. 486 * </p> 487 * <p> 488 * Notice that getResult() also returns {@code false} if no {@link #ACTION_DROP} is sent. This 489 * happens, for example, when the user releases the drag shadow over an area outside of the 490 * application. In this case, the system sends out {@link #ACTION_DRAG_ENDED} for the current 491 * operation, but never sends out {@link #ACTION_DROP}. 492 * </p> 493 * @return {@code true} if a drag event listener returned {@code true} in response to 494 * {@link #ACTION_DROP}. If the system did not send {@link #ACTION_DROP} before 495 * {@link #ACTION_DRAG_ENDED}, or if the listener returned {@code false} in response to 496 * {@link #ACTION_DROP}, then {@code false} is returned. 497 */ getResult()498 public boolean getResult() { 499 return mDragResult; 500 } 501 502 /** 503 * Recycle the DragEvent, to be re-used by a later caller. After calling 504 * this function you must never touch the event again. 505 * 506 * @hide 507 */ recycle()508 public final void recycle() { 509 // Ensure recycle is only called once! 510 if (TRACK_RECYCLED_LOCATION) { 511 if (mRecycledLocation != null) { 512 throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); 513 } 514 mRecycledLocation = new RuntimeException("Last recycled here"); 515 } else { 516 if (mRecycled) { 517 throw new RuntimeException(toString() + " recycled twice!"); 518 } 519 mRecycled = true; 520 } 521 522 mClipData = null; 523 mClipDescription = null; 524 mLocalState = null; 525 mEventHandlerWasCalled = false; 526 527 synchronized (gRecyclerLock) { 528 if (gRecyclerUsed < MAX_RECYCLED) { 529 gRecyclerUsed++; 530 mNext = gRecyclerTop; 531 gRecyclerTop = this; 532 } 533 } 534 } 535 536 /** 537 * Returns a string that represents the symbolic name of the specified unmasked action 538 * such as "ACTION_DRAG_START", "ACTION_DRAG_END" or an equivalent numeric constant 539 * such as "35" if unknown. 540 * 541 * @param action The action. 542 * @return The symbolic name of the specified action. 543 * @see #getAction() 544 * @hide 545 */ actionToString(int action)546 public static String actionToString(int action) { 547 switch (action) { 548 case ACTION_DRAG_STARTED: 549 return "ACTION_DRAG_STARTED"; 550 case ACTION_DRAG_LOCATION: 551 return "ACTION_DRAG_LOCATION"; 552 case ACTION_DROP: 553 return "ACTION_DROP"; 554 case ACTION_DRAG_ENDED: 555 return "ACTION_DRAG_ENDED"; 556 case ACTION_DRAG_ENTERED: 557 return "ACTION_DRAG_ENTERED"; 558 case ACTION_DRAG_EXITED: 559 return "ACTION_DRAG_EXITED"; 560 } 561 return Integer.toString(action); 562 } 563 564 /** 565 * Returns a string containing a concise, human-readable representation of this DragEvent 566 * object. 567 * @return A string representation of the DragEvent object. 568 */ 569 @Override toString()570 public String toString() { 571 return "DragEvent{" + Integer.toHexString(System.identityHashCode(this)) 572 + " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription 573 + " data=" + mClipData + " local=" + mLocalState + " result=" + mDragResult 574 + "}"; 575 } 576 577 /* Parcelable interface */ 578 579 /** 580 * Returns information about the {@link android.os.Parcel} representation of this DragEvent 581 * object. 582 * @return Information about the {@link android.os.Parcel} representation. 583 */ describeContents()584 public int describeContents() { 585 return 0; 586 } 587 588 /** 589 * Creates a {@link android.os.Parcel} object from this DragEvent object. 590 * @param dest A {@link android.os.Parcel} object in which to put the DragEvent object. 591 * @param flags Flags to store in the Parcel. 592 */ writeToParcel(Parcel dest, int flags)593 public void writeToParcel(Parcel dest, int flags) { 594 dest.writeInt(mAction); 595 dest.writeFloat(mX); 596 dest.writeFloat(mY); 597 dest.writeFloat(mOffsetX); 598 dest.writeFloat(mOffsetY); 599 dest.writeInt(mFlags); 600 dest.writeInt(mDragResult ? 1 : 0); 601 if (mClipData == null) { 602 dest.writeInt(0); 603 } else { 604 dest.writeInt(1); 605 mClipData.writeToParcel(dest, flags); 606 } 607 if (mClipDescription == null) { 608 dest.writeInt(0); 609 } else { 610 dest.writeInt(1); 611 mClipDescription.writeToParcel(dest, flags); 612 } 613 if (mDragSurface == null) { 614 dest.writeInt(0); 615 } else { 616 dest.writeInt(1); 617 mDragSurface.writeToParcel(dest, flags); 618 } 619 if (mDragAndDropPermissions == null) { 620 dest.writeInt(0); 621 } else { 622 dest.writeInt(1); 623 dest.writeStrongBinder(mDragAndDropPermissions.asBinder()); 624 } 625 } 626 627 /** 628 * A container for creating a DragEvent from a Parcel. 629 */ 630 public static final @android.annotation.NonNull Parcelable.Creator<DragEvent> CREATOR = 631 new Parcelable.Creator<DragEvent>() { 632 public DragEvent createFromParcel(Parcel in) { 633 DragEvent event = DragEvent.obtain(); 634 event.mAction = in.readInt(); 635 event.mX = in.readFloat(); 636 event.mY = in.readFloat(); 637 event.mOffsetX = in.readFloat(); 638 event.mOffsetY = in.readFloat(); 639 event.mFlags = in.readInt(); 640 event.mDragResult = (in.readInt() != 0); 641 if (in.readInt() != 0) { 642 event.mClipData = ClipData.CREATOR.createFromParcel(in); 643 } 644 if (in.readInt() != 0) { 645 event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in); 646 } 647 if (in.readInt() != 0) { 648 event.mDragSurface = SurfaceControl.CREATOR.createFromParcel(in); 649 event.mDragSurface.setUnreleasedWarningCallSite("DragEvent"); 650 } 651 if (in.readInt() != 0) { 652 event.mDragAndDropPermissions = 653 IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder()); 654 } 655 return event; 656 } 657 658 public DragEvent[] newArray(int size) { 659 return new DragEvent[size]; 660 } 661 }; 662 } 663