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 View#DRAG_FLAG_* flags used to start the current drag, only provided if the target window 161 * has the {@link WindowManager.LayoutParams#PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP} flag 162 * and is only sent with {@link #ACTION_DRAG_STARTED} and {@link #ACTION_DROP}. 163 */ 164 private int mFlags; 165 166 private DragEvent mNext; 167 private RuntimeException mRecycledLocation; 168 private boolean mRecycled; 169 170 private static final int MAX_RECYCLED = 10; 171 private static final Object gRecyclerLock = new Object(); 172 private static int gRecyclerUsed = 0; 173 private static DragEvent gRecyclerTop = null; 174 175 /** 176 * Action constant returned by {@link #getAction()}: Signals the start of a 177 * drag and drop operation. The View should return {@code true} from its 178 * {@link View#onDragEvent(DragEvent) onDragEvent()} handler method or 179 * {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} listener 180 * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata 181 * from {@link #getClipDescription()} to determine if they can accept the data contained in 182 * this drag. For an operation that doesn't represent data transfer, these methods may 183 * perform other actions to determine whether or not the View should accept the data. 184 * If the View wants to indicate that it is a valid drop target, it can also react by 185 * changing its appearance. 186 * <p> 187 * Views added or becoming visible for the first time during a drag operation receive this 188 * event when they are added or becoming visible. 189 * </p> 190 * <p> 191 * A View only receives further drag events for the drag operation if it returns {@code true} 192 * in response to ACTION_DRAG_STARTED. 193 * </p> 194 * @see #ACTION_DRAG_ENDED 195 * @see #getX() 196 * @see #getY() 197 */ 198 public static final int ACTION_DRAG_STARTED = 1; 199 200 /** 201 * Action constant returned by {@link #getAction()}: Sent to a View after 202 * {@link #ACTION_DRAG_ENTERED} while the drag shadow is still within the View object's bounding 203 * box, but not within a descendant view that can accept the data. The {@link #getX()} and 204 * {@link #getY()} methods supply 205 * the X and Y position of the drag point within the View object's bounding box. 206 * <p> 207 * A View receives an {@link #ACTION_DRAG_ENTERED} event before receiving any 208 * ACTION_DRAG_LOCATION events. 209 * </p> 210 * <p> 211 * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the 212 * drag shadow out of the View object's bounding box or into a descendant view that can accept 213 * the data. If the user moves the drag shadow back into the View object's bounding box or out 214 * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again 215 * before receiving any more ACTION_DRAG_LOCATION events. 216 * </p> 217 * @see #ACTION_DRAG_ENTERED 218 * @see #getX() 219 * @see #getY() 220 */ 221 public static final int ACTION_DRAG_LOCATION = 2; 222 223 /** 224 * Action constant returned by {@link #getAction()}: Signals to a View that the user 225 * has released the drag shadow, and the drag point is within the bounding box of the View and 226 * not within a descendant view that can accept the data. 227 * The View should retrieve the data from the DragEvent by calling {@link #getClipData()}. 228 * The methods {@link #getX()} and {@link #getY()} return the X and Y position of the drop point 229 * within the View object's bounding box. 230 * <p> 231 * The View should return {@code true} from its {@link View#onDragEvent(DragEvent)} 232 * handler or {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} 233 * listener if it accepted the drop, and {@code false} if it ignored the drop. 234 * </p> 235 * <p> 236 * The View can also react to this action by changing its appearance. 237 * </p> 238 * @see #getClipData() 239 * @see #getX() 240 * @see #getY() 241 */ 242 public static final int ACTION_DROP = 3; 243 244 /** 245 * Action constant returned by {@link #getAction()}: Signals to a View that the drag and drop 246 * operation has concluded. A View that changed its appearance during the operation should 247 * return to its usual drawing state in response to this event. 248 * <p> 249 * All views with listeners that returned boolean <code>true</code> for the ACTION_DRAG_STARTED 250 * event will receive the ACTION_DRAG_ENDED event even if they are not currently visible when 251 * the drag ends. Views removed during the drag operation won't receive the ACTION_DRAG_ENDED 252 * event. 253 * </p> 254 * <p> 255 * The View object can call {@link #getResult()} to see the result of the operation. 256 * If a View returned {@code true} in response to {@link #ACTION_DROP}, then 257 * getResult() returns {@code true}, otherwise it returns {@code false}. 258 * </p> 259 * @see #ACTION_DRAG_STARTED 260 * @see #getResult() 261 */ 262 public static final int ACTION_DRAG_ENDED = 4; 263 264 /** 265 * Action constant returned by {@link #getAction()}: Signals to a View that the drag point has 266 * entered the bounding box of the View. 267 * <p> 268 * If the View can accept a drop, it can react to ACTION_DRAG_ENTERED 269 * by changing its appearance in a way that tells the user that the View is the current 270 * drop target. 271 * </p> 272 * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the 273 * drag shadow out of the View object's bounding box or into a descendant view that can accept 274 * the data. If the user moves the drag shadow back into the View object's bounding box or out 275 * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again 276 * before receiving any more ACTION_DRAG_LOCATION events. 277 * </p> 278 * @see #ACTION_DRAG_ENTERED 279 * @see #ACTION_DRAG_LOCATION 280 */ 281 public static final int ACTION_DRAG_ENTERED = 5; 282 283 /** 284 * Action constant returned by {@link #getAction()}: Signals that the user has moved the 285 * drag shadow out of the bounding box of the View or into a descendant view that can accept 286 * the data. 287 * The View can react by changing its appearance in a way that tells the user that 288 * View is no longer the immediate drop target. 289 * <p> 290 * After the system sends an ACTION_DRAG_EXITED event to the View, the View receives no more 291 * ACTION_DRAG_LOCATION events until the user drags the drag shadow back over the View. 292 * </p> 293 * 294 */ 295 public static final int ACTION_DRAG_EXITED = 6; 296 DragEvent()297 private DragEvent() { 298 } 299 init(int action, float x, float y, float offsetX, float offsetY, int flags, ClipDescription description, ClipData data, SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result)300 private void init(int action, float x, float y, float offsetX, float offsetY, int flags, 301 ClipDescription description, ClipData data, SurfaceControl dragSurface, 302 IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result) { 303 mAction = action; 304 mX = x; 305 mY = y; 306 mOffsetX = offsetX; 307 mOffsetY = offsetY; 308 mFlags = flags; 309 mClipDescription = description; 310 mClipData = data; 311 mDragSurface = dragSurface; 312 mDragAndDropPermissions = dragAndDropPermissions; 313 mLocalState = localState; 314 mDragResult = result; 315 } 316 obtain()317 static DragEvent obtain() { 318 return DragEvent.obtain(0, 0f, 0f, 0f, 0f, 0, null, null, null, null, null, false); 319 } 320 321 /** @hide */ obtain(int action, float x, float y, float offsetX, float offsetY, int flags, Object localState, ClipDescription description, ClipData data, SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, boolean result)322 public static DragEvent obtain(int action, float x, float y, float offsetX, float offsetY, 323 int flags, Object localState, ClipDescription description, ClipData data, 324 SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions, 325 boolean result) { 326 final DragEvent ev; 327 synchronized (gRecyclerLock) { 328 if (gRecyclerTop == null) { 329 ev = new DragEvent(); 330 ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface, 331 dragAndDropPermissions, localState, result); 332 return ev; 333 } 334 ev = gRecyclerTop; 335 gRecyclerTop = ev.mNext; 336 gRecyclerUsed -= 1; 337 } 338 ev.mRecycledLocation = null; 339 ev.mRecycled = false; 340 ev.mNext = null; 341 342 ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface, 343 dragAndDropPermissions, localState, result); 344 345 return ev; 346 } 347 348 /** @hide */ 349 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) obtain(DragEvent source)350 public static DragEvent obtain(DragEvent source) { 351 return obtain(source.mAction, source.mX, source.mY, source.mOffsetX, source.mOffsetY, 352 source.mFlags, source.mLocalState, source.mClipDescription, source.mClipData, 353 source.mDragSurface, source.mDragAndDropPermissions, source.mDragResult); 354 } 355 356 /** 357 * Inspect the action value of this event. 358 * @return One of the following action constants, in the order in which they usually occur 359 * during a drag and drop operation: 360 * <ul> 361 * <li>{@link #ACTION_DRAG_STARTED}</li> 362 * <li>{@link #ACTION_DRAG_ENTERED}</li> 363 * <li>{@link #ACTION_DRAG_LOCATION}</li> 364 * <li>{@link #ACTION_DROP}</li> 365 * <li>{@link #ACTION_DRAG_EXITED}</li> 366 * <li>{@link #ACTION_DRAG_ENDED}</li> 367 * </ul> 368 */ getAction()369 public int getAction() { 370 return mAction; 371 } 372 373 /** 374 * Gets the X coordinate of the drag point. The value is only valid if the event action is 375 * {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_LOCATION} or {@link #ACTION_DROP}. 376 * @return The current drag point's X coordinate 377 */ getX()378 public float getX() { 379 return mX; 380 } 381 382 /** 383 * Gets the Y coordinate of the drag point. The value is only valid if the event action is 384 * {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_LOCATION} or {@link #ACTION_DROP}. 385 * @return The current drag point's Y coordinate 386 */ getY()387 public float getY() { 388 return mY; 389 } 390 391 /** @hide */ getOffsetX()392 public float getOffsetX() { 393 return mOffsetX; 394 } 395 396 /** @hide */ getOffsetY()397 public float getOffsetY() { 398 return mOffsetY; 399 } 400 401 /** 402 * Returns the {@link android.content.ClipData} object sent to the system as part of the call 403 * to 404 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 405 * startDragAndDrop()}. 406 * This method only returns valid data if the event action is {@link #ACTION_DROP}. 407 * @return The ClipData sent to the system by startDragAndDrop(). 408 */ getClipData()409 public ClipData getClipData() { 410 return mClipData; 411 } 412 413 /** 414 * Returns the {@link android.content.ClipDescription} object contained in the 415 * {@link android.content.ClipData} object sent to the system as part of the call to 416 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 417 * startDragAndDrop()}. 418 * The drag handler or listener for a View can use the metadata in this object to decide if the 419 * View can accept the dragged View object's data. 420 * <p> 421 * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}. 422 * @return The ClipDescription that was part of the ClipData sent to the system by 423 * startDragAndDrop(). 424 */ getClipDescription()425 public ClipDescription getClipDescription() { 426 return mClipDescription; 427 } 428 429 /** @hide */ getDragSurface()430 public SurfaceControl getDragSurface() { 431 return mDragSurface; 432 } 433 434 /** @hide */ getDragFlags()435 public int getDragFlags() { 436 return mFlags; 437 } 438 439 /** @hide */ getDragAndDropPermissions()440 public IDragAndDropPermissions getDragAndDropPermissions() { 441 return mDragAndDropPermissions; 442 } 443 444 /** 445 * Returns the local state object sent to the system as part of the call to 446 * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int) 447 * startDragAndDrop()}. 448 * The object is intended to provide local information about the drag and drop operation. For 449 * example, it can indicate whether the drag and drop operation is a copy or a move. 450 * <p> 451 * The local state is available only to views in the activity which has started the drag 452 * operation. In all other activities this method will return null 453 * </p> 454 * <p> 455 * This method returns valid data for all event actions. 456 * </p> 457 * @return The local state object sent to the system by startDragAndDrop(). 458 */ getLocalState()459 public Object getLocalState() { 460 return mLocalState; 461 } 462 463 /** 464 * <p> 465 * Returns an indication of the result of the drag and drop operation. 466 * This method only returns valid data if the action type is {@link #ACTION_DRAG_ENDED}. 467 * The return value depends on what happens after the user releases the drag shadow. 468 * </p> 469 * <p> 470 * If the user releases the drag shadow on a View that can accept a drop, the system sends an 471 * {@link #ACTION_DROP} event to the View object's drag event listener. If the listener 472 * returns {@code true}, then getResult() will return {@code true}. 473 * If the listener returns {@code false}, then getResult() returns {@code false}. 474 * </p> 475 * <p> 476 * Notice that getResult() also returns {@code false} if no {@link #ACTION_DROP} is sent. This 477 * happens, for example, when the user releases the drag shadow over an area outside of the 478 * application. In this case, the system sends out {@link #ACTION_DRAG_ENDED} for the current 479 * operation, but never sends out {@link #ACTION_DROP}. 480 * </p> 481 * @return {@code true} if a drag event listener returned {@code true} in response to 482 * {@link #ACTION_DROP}. If the system did not send {@link #ACTION_DROP} before 483 * {@link #ACTION_DRAG_ENDED}, or if the listener returned {@code false} in response to 484 * {@link #ACTION_DROP}, then {@code false} is returned. 485 */ getResult()486 public boolean getResult() { 487 return mDragResult; 488 } 489 490 /** 491 * Recycle the DragEvent, to be re-used by a later caller. After calling 492 * this function you must never touch the event again. 493 * 494 * @hide 495 */ recycle()496 public final void recycle() { 497 // Ensure recycle is only called once! 498 if (TRACK_RECYCLED_LOCATION) { 499 if (mRecycledLocation != null) { 500 throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); 501 } 502 mRecycledLocation = new RuntimeException("Last recycled here"); 503 } else { 504 if (mRecycled) { 505 throw new RuntimeException(toString() + " recycled twice!"); 506 } 507 mRecycled = true; 508 } 509 510 mClipData = null; 511 mClipDescription = null; 512 mLocalState = null; 513 mEventHandlerWasCalled = false; 514 515 synchronized (gRecyclerLock) { 516 if (gRecyclerUsed < MAX_RECYCLED) { 517 gRecyclerUsed++; 518 mNext = gRecyclerTop; 519 gRecyclerTop = this; 520 } 521 } 522 } 523 524 /** 525 * Returns a string that represents the symbolic name of the specified unmasked action 526 * such as "ACTION_DRAG_START", "ACTION_DRAG_END" or an equivalent numeric constant 527 * such as "35" if unknown. 528 * 529 * @param action The action. 530 * @return The symbolic name of the specified action. 531 * @see #getAction() 532 * @hide 533 */ actionToString(int action)534 public static String actionToString(int action) { 535 switch (action) { 536 case ACTION_DRAG_STARTED: 537 return "ACTION_DRAG_STARTED"; 538 case ACTION_DRAG_LOCATION: 539 return "ACTION_DRAG_LOCATION"; 540 case ACTION_DROP: 541 return "ACTION_DROP"; 542 case ACTION_DRAG_ENDED: 543 return "ACTION_DRAG_ENDED"; 544 case ACTION_DRAG_ENTERED: 545 return "ACTION_DRAG_ENTERED"; 546 case ACTION_DRAG_EXITED: 547 return "ACTION_DRAG_EXITED"; 548 } 549 return Integer.toString(action); 550 } 551 552 /** 553 * Returns a string containing a concise, human-readable representation of this DragEvent 554 * object. 555 * @return A string representation of the DragEvent object. 556 */ 557 @Override toString()558 public String toString() { 559 return "DragEvent{" + Integer.toHexString(System.identityHashCode(this)) 560 + " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription 561 + " data=" + mClipData + " local=" + mLocalState + " result=" + mDragResult 562 + "}"; 563 } 564 565 /* Parcelable interface */ 566 567 /** 568 * Returns information about the {@link android.os.Parcel} representation of this DragEvent 569 * object. 570 * @return Information about the {@link android.os.Parcel} representation. 571 */ describeContents()572 public int describeContents() { 573 return 0; 574 } 575 576 /** 577 * Creates a {@link android.os.Parcel} object from this DragEvent object. 578 * @param dest A {@link android.os.Parcel} object in which to put the DragEvent object. 579 * @param flags Flags to store in the Parcel. 580 */ writeToParcel(Parcel dest, int flags)581 public void writeToParcel(Parcel dest, int flags) { 582 dest.writeInt(mAction); 583 dest.writeFloat(mX); 584 dest.writeFloat(mY); 585 dest.writeFloat(mOffsetX); 586 dest.writeFloat(mOffsetY); 587 dest.writeInt(mFlags); 588 dest.writeInt(mDragResult ? 1 : 0); 589 if (mClipData == null) { 590 dest.writeInt(0); 591 } else { 592 dest.writeInt(1); 593 mClipData.writeToParcel(dest, flags); 594 } 595 if (mClipDescription == null) { 596 dest.writeInt(0); 597 } else { 598 dest.writeInt(1); 599 mClipDescription.writeToParcel(dest, flags); 600 } 601 if (mDragSurface == null) { 602 dest.writeInt(0); 603 } else { 604 dest.writeInt(1); 605 mDragSurface.writeToParcel(dest, flags); 606 } 607 if (mDragAndDropPermissions == null) { 608 dest.writeInt(0); 609 } else { 610 dest.writeInt(1); 611 dest.writeStrongBinder(mDragAndDropPermissions.asBinder()); 612 } 613 } 614 615 /** 616 * A container for creating a DragEvent from a Parcel. 617 */ 618 public static final @android.annotation.NonNull Parcelable.Creator<DragEvent> CREATOR = 619 new Parcelable.Creator<DragEvent>() { 620 public DragEvent createFromParcel(Parcel in) { 621 DragEvent event = DragEvent.obtain(); 622 event.mAction = in.readInt(); 623 event.mX = in.readFloat(); 624 event.mY = in.readFloat(); 625 event.mOffsetX = in.readFloat(); 626 event.mOffsetY = in.readFloat(); 627 event.mFlags = in.readInt(); 628 event.mDragResult = (in.readInt() != 0); 629 if (in.readInt() != 0) { 630 event.mClipData = ClipData.CREATOR.createFromParcel(in); 631 } 632 if (in.readInt() != 0) { 633 event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in); 634 } 635 if (in.readInt() != 0) { 636 event.mDragSurface = SurfaceControl.CREATOR.createFromParcel(in); 637 event.mDragSurface.setUnreleasedWarningCallSite("DragEvent"); 638 } 639 if (in.readInt() != 0) { 640 event.mDragAndDropPermissions = 641 IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder()); 642 } 643 return event; 644 } 645 646 public DragEvent[] newArray(int size) { 647 return new DragEvent[size]; 648 } 649 }; 650 } 651