API CHANGE: drags can now carry an originator-only object payload

When calling startDrag(), the app can now supply an Object to be passed
along in every DragEvent that the app winds up receiving itself.  This
object is *not* passed to any other applications; it's strictly app-
local.  The purpose is to allow state tracking/management to be done
directly through the drag mechanism rather than requiring out-of-band
code.

An example of the utility here might be TextEdit widgets.  A drag that
starts in one TextEdit but ends in a different one should be treated as
a copy/paste operation, where the originating TextEdit is not altered.
However, a drag that starts and ends in the *same* TextEdit is a 'move'
operation within that TextEdit; the text is removed from its original
position and inserted at the drop point.  To support this easily, the
drag/drop code in TextEdit can now pass a pointer to the originating
view as the local state object.  Then, the drop recipient could tell
whether the drag started within the same TextEdit without needing to
implement any other out-of-band state tracking.

This CL (and its accompanying CLs in a few other packages where the
startDrag() API is being used) adds the new local-state parameter to
the API, but does not actually change the behavior of any existing
clients.

Change-Id: Icba73b2ab4a650b7a94485a19633065b0ef9058c
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 77083a9..17d413a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -228,6 +228,7 @@
     /* Drag/drop */
     ClipDescription mDragDescription;
     View mCurrentDragView;
+    Object mLocalDragState;
     final PointF mDragPoint = new PointF();
     final PointF mLastTouchPoint = new PointF();
 
@@ -2680,6 +2681,10 @@
     }
 
     /* drag/drop */
+    void setLocalDragState(Object obj) {
+        mLocalDragState = obj;
+    }
+
     private void handleDragEvent(DragEvent event) {
         // From the root, only drag start/end/location are dispatched.  entered/exited
         // are determined and dispatched by the viewgroup hierarchy, who then report
@@ -2738,7 +2743,7 @@
                     }
                 }
 
-                // Report the drop result if necessary
+                // Report the drop result when we're done
                 if (what == DragEvent.ACTION_DROP) {
                     try {
                         Log.i(TAG, "Reporting drop result: " + result);
@@ -2747,6 +2752,12 @@
                         Log.e(TAG, "Unable to report drop result");
                     }
                 }
+
+                // When the drag operation ends, release any local state object
+                // that may have been in use
+                if (what == DragEvent.ACTION_DRAG_ENDED) {
+                    setLocalDragState(null);
+                }
             }
         }
         event.recycle();
@@ -3063,6 +3074,7 @@
         } else {
             what = DISPATCH_DRAG_EVENT;
         }
+        event.mLocalState = mLocalDragState;    // only present when this app called startDrag()
         Message msg = obtainMessage(what, event);
         sendMessage(msg);
     }