Add view/drawable states for drag-accepting / drag-hovered

Added new drag_can_accept and drag_hovered XML attributes and the View
logic to support them.  Drawable states are now refreshed automatically
when a drag starts/ends and when a drag crosses the boundary of a
participating view.

Change-Id: I25f8ee02c83b3fa4f27201997d7eabf4be653fd8
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 96cddfa..0ef56cc 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1305,6 +1305,8 @@
     static final int VIEW_STATE_ACTIVATED = 1 << 5;
     static final int VIEW_STATE_ACCELERATED = 1 << 6;
     static final int VIEW_STATE_HOVERED = 1 << 7;
+    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
+    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
 
     static final int[] VIEW_STATE_IDS = new int[] {
         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
@@ -1315,6 +1317,8 @@
         R.attr.state_activated,         VIEW_STATE_ACTIVATED,
         R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
         R.attr.state_hovered,           VIEW_STATE_HOVERED,
+        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
+        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED,
     };
 
     static {
@@ -1651,6 +1655,27 @@
      */
     static final int INVALIDATED                  = 0x80000000;
 
+    /* Masks for mPrivateFlags2 */
+
+    /**
+     * Indicates that this view has reported that it can accept the current drag's content.
+     * Cleared when the drag operation concludes.
+     * @hide
+     */
+    static final int DRAG_CAN_ACCEPT              = 0x00000001;
+
+    /**
+     * Indicates that this view is currently directly under the drag location in a
+     * drag-and-drop operation involving content that it can accept.  Cleared when
+     * the drag exits the view, or when the drag operation concludes.
+     * @hide
+     */
+    static final int DRAG_HOVERED                 = 0x00000002;
+
+    /* End of masks for mPrivateFlags2 */
+
+    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+
     /**
      * Always allow a user to over-scroll this view, provided it is a
      * view that can scroll.
@@ -1822,6 +1847,7 @@
         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
     })
     int mPrivateFlags;
+    int mPrivateFlags2;
 
     /**
      * This view's request for the visibility of the status bar.
@@ -2251,12 +2277,6 @@
     private ViewPropertyAnimator mAnimator = null;
 
     /**
-     * Cache drag/drop state
-     *
-     */
-    boolean mCanAcceptDrop;
-
-    /**
      * Flag indicating that a drag can cross window boundaries.  When
      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
      * with this flag set, all visible applications will be able to participate
@@ -10035,6 +10055,10 @@
         }
         if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
 
+        final int privateFlags2 = mPrivateFlags2;
+        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
+        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
+
         drawableState = VIEW_STATE_SETS[viewStateIndex];
 
         //noinspection ConstantIfStatement
@@ -11701,6 +11725,10 @@
         return onDragEvent(event);
     }
 
+    boolean canAcceptDrag() {
+        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+    }
+
     /**
      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
      * it is ever exposed at all.