Merge "Show IME when search query != null after rotation" into ub-launcher3-calgary-polish
diff --git a/res/drawable-hdpi/ic_all_apps_bg_hand.png b/res/drawable-hdpi/ic_all_apps_bg_hand.png
index 43b1bed..dff2f54 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_1.png b/res/drawable-hdpi/ic_all_apps_bg_icon_1.png
deleted file mode 100644
index d2c4cc1..0000000
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_2.png b/res/drawable-hdpi/ic_all_apps_bg_icon_2.png
deleted file mode 100644
index 57b7456..0000000
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_3.png b/res/drawable-hdpi/ic_all_apps_bg_icon_3.png
deleted file mode 100644
index 54fe70b..0000000
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_4.png b/res/drawable-hdpi/ic_all_apps_bg_icon_4.png
deleted file mode 100644
index 9c0f777..0000000
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_hand.png b/res/drawable-mdpi/ic_all_apps_bg_hand.png
index 8868d6b..0d1d7bb 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_1.png b/res/drawable-mdpi/ic_all_apps_bg_icon_1.png
deleted file mode 100644
index 4c78288..0000000
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_2.png b/res/drawable-mdpi/ic_all_apps_bg_icon_2.png
deleted file mode 100644
index 0ed311b..0000000
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_3.png b/res/drawable-mdpi/ic_all_apps_bg_icon_3.png
deleted file mode 100644
index 2aa3d4e..0000000
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_4.png b/res/drawable-mdpi/ic_all_apps_bg_icon_4.png
deleted file mode 100644
index 2cdea9c..0000000
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_hand.png b/res/drawable-xhdpi/ic_all_apps_bg_hand.png
index 8a67245..e727d37 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png
deleted file mode 100644
index c0ebaed..0000000
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png
deleted file mode 100644
index 71cf250..0000000
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png
deleted file mode 100644
index 3c69fc5..0000000
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png
deleted file mode 100644
index 5f6ca38..0000000
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_hand.png b/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
index ed694f8..fffcc6b 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png
deleted file mode 100644
index 5cb0427..0000000
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png
deleted file mode 100644
index cd0322b..0000000
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png
deleted file mode 100644
index 19ffc2d..0000000
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png
deleted file mode 100644
index 311c3df..0000000
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png b/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
index 615374a..4d065d8 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png
deleted file mode 100644
index 10f8c41..0000000
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png
deleted file mode 100644
index 102d925..0000000
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png
deleted file mode 100644
index 9be5b7a..0000000
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png
deleted file mode 100644
index d7fb29b..0000000
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bg_pill_focused.xml b/res/drawable/bg_pill_focused.xml
new file mode 100644
index 0000000..37afad0
--- /dev/null
+++ b/res/drawable/bg_pill_focused.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true">
+        <shape xmlns:android="http://schemas.android.com/apk/res/android"
+               android:shape="rectangle">
+            <stroke android:color="#616161" android:width="2dp"/>
+            <corners android:radius="@dimen/bg_pill_radius" />
+        </shape>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/ic_all_apps_bg_icon_1.xml b/res/drawable/ic_all_apps_bg_icon_1.xml
new file mode 100644
index 0000000..c9c0a75
--- /dev/null
+++ b/res/drawable/ic_all_apps_bg_icon_1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#1A000000"
+        android:pathData="M44.28,30.96c4.84-10.68,0.09-23.27-10.59-28.11S10.42,2.74,5.58,13.42
+        C1,23.54,6.5,35.92,16.62,40.51l0,0l-3.23,7.12C27.84,47,39.79,40.86,44.28,30.96z" />
+    <path
+        android:fillColor="#E0E0E0"
+        android:pathData="M41.75,30.05c4.84-10.68,0.09-23.27-10.59-28.11S7.9,1.83,3.06,12.51
+        c-4.59,10.12,0.92,22.5,11.03,27.09l0,0l-3.23,7.12C25.31,46.09,37.26,39.94,41.75,30.05z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_all_apps_bg_icon_2.xml b/res/drawable/ic_all_apps_bg_icon_2.xml
new file mode 100644
index 0000000..b6269e3
--- /dev/null
+++ b/res/drawable/ic_all_apps_bg_icon_2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#1A000000"
+        android:pathData="M20.54,44.59c0.57-0.04,1.15-0.38,1.67-1.04l24.23-30.62c0.62-0.78,0.77-1.54,0.52-2.12
+        c-0.25-0.58-0.9-0.99-1.89-1.1L6.2,5.99C5.39,5.91,4.74,6.08,4.32,6.44l0,0C3.7,6.97,3.55,7.88,4.01,8.96l14.54,34.09
+        C19,44.13,19.75,44.65,20.54,44.59L20.54,44.59z" />
+    <path
+        android:fillColor="#E0E0E0"
+        android:pathData="M18.49,43.22c0.57-0.04,1.15-0.38,1.67-1.04l24.23-30.62c0.62-0.78,0.77-1.54,0.52-2.12
+        c-0.25-0.58-0.9-0.99-1.89-1.1L4.15,4.62C3.34,4.54,2.69,4.71,2.27,5.08l0,0C1.65,5.6,1.5,6.52,1.96,7.6L16.5,41.69
+        C16.96,42.76,17.7,43.28,18.49,43.22L18.49,43.22z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_all_apps_bg_icon_3.xml b/res/drawable/ic_all_apps_bg_icon_3.xml
new file mode 100644
index 0000000..4c255a9
--- /dev/null
+++ b/res/drawable/ic_all_apps_bg_icon_3.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#1A000000"
+        android:pathData="M25.18,1.27c-12.32,0-23.41,9.99-23.41,22.31s11.09,22.31,23.41,22.31
+        s22.31-9.99,22.31-22.31S37.5,1.27,25.18,1.27z M25.18,33.55c-5.5,0-14.35-5.1-14.35-10.6s8.32-12.19,13.82-12.19
+        c5.5,0,10.49,7.33,10.49,12.83S30.68,33.55,25.18,33.55z" />
+    <path
+        android:fillColor="#E0E0E0"
+        android:pathData="M22.93,0.22c-12.32,0-22.31,9.99-22.31,22.31s9.99,22.31,22.31,22.31
+        s22.31-9.99,22.31-22.31S35.25,0.22,22.93,0.22z M22.93,32.5c-5.5,0-9.97-4.46-9.97-9.97s4.46-9.97,9.97-9.97
+        c5.5,0,9.97,4.46,9.97,9.97S28.43,32.5,22.93,32.5z" />
+    <path
+        android:fillColor="#E0E0E0"
+        android:pathData="M14.81,22.53a8.12,8.12 0 1,0 16.24,0a8.12,8.12 0 1,0 -16.24,0z" />
+</vector>
diff --git a/res/drawable/ic_all_apps_bg_icon_4.xml b/res/drawable/ic_all_apps_bg_icon_4.xml
new file mode 100644
index 0000000..12e05bc
--- /dev/null
+++ b/res/drawable/ic_all_apps_bg_icon_4.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#1A000000"
+        android:pathData="M11.53,8.02l23.39-5.73c1.61-0.39,3.25,0.6,3.64,2.21l7.64,31.19
+        c0.39,1.61-0.6,3.25-2.21,3.64L12.8,46.97c-1.61,0.39-3.25-0.6-3.64-2.21L3.43,21.37L11.53,8.02z" />
+    <path
+        android:fillColor="#E0E0E0"
+        android:pathData="M9.2,6.53L32.59,0.8C34.2,0.4,35.84,1.4,36.23,3l7.64,31.19c0.39,1.61-0.6,3.25-2.21,3.64
+        l-31.19,7.64c-1.61,0.39-3.25-0.6-3.64-2.21L1.11,19.87L9.2,6.53z" />
+    <path
+        android:fillColor="#1A000000"
+        android:pathData="M9.27,6.47l1.91,7.8c0.4,1.62-0.59,3.24-2.21,3.64l-7.8,1.91L9.27,6.47z" />
+</vector>
\ No newline at end of file
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 49bac3b..a2e2f9b 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -56,10 +56,8 @@
 
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
-        <com.android.launcher3.pageindicators.PageIndicatorLineCaret
-            android:id="@+id/page_indicator"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
+        <include layout="@layout/page_indicator"
+            android:id="@+id/page_indicator" />
 
         <include
             android:id="@+id/drop_target_bar"
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 81d2e1b..12c01b7 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -59,10 +59,8 @@
 
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
-        <com.android.launcher3.pageindicators.PageIndicatorLineCaret
-            android:id="@+id/page_indicator"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
+        <include layout="@layout/page_indicator"
+                 android:id="@+id/page_indicator" />
 
         <include
             layout="@layout/qsb_container"
diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml
index 2d66d72..7b42ec7 100644
--- a/res/layout/deep_shortcut.xml
+++ b/res/layout/deep_shortcut.xml
@@ -26,7 +26,8 @@
         style="@style/Icon.DeepShortcut"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:focusable="true" />
+        android:focusable="true"
+        android:background="@drawable/bg_pill_focused" />
 
     <View
         android:id="@+id/deep_shortcut_icon"
diff --git a/res/layout/page_indicator.xml b/res/layout/page_indicator.xml
new file mode 100644
index 0000000..2e1b57f
--- /dev/null
+++ b/res/layout/page_indicator.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<com.android.launcher3.pageindicators.PageIndicatorLineCaret
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/dynamic_grid_page_indicator_height">
+        <ImageView
+            android:id="@+id/all_apps_handle"
+            android:layout_width="48dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:scaleType="centerInside"/>
+</com.android.launcher3.pageindicators.PageIndicatorLineCaret>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 87ef78b..1ae4685 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,7 +19,6 @@
     <dimen name="dynamic_grid_edge_margin">8dp</dimen>
     <dimen name="dynamic_grid_page_indicator_height">28dp</dimen>
     <dimen name="dynamic_grid_page_indicator_line_height">1dp</dimen>
-    <dimen name="dynamic_grid_page_indicator_extra_touch_height">12dp</dimen>
     <dimen name="dynamic_grid_page_indicator_gutter_width_left_nav_bar">38dp</dimen>
     <dimen name="dynamic_grid_page_indicator_gutter_width_right_nav_bar">48dp</dimen>
     <dimen name="dynamic_grid_icon_drawable_padding">8dp</dimen>
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 0f6073e..2dde7ca 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -43,6 +43,7 @@
 
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.util.Thunk;
 
@@ -199,8 +200,8 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
-        mActive = supportsDrop(source, info);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        mActive = supportsDrop(dragObject.dragSource, dragObject.dragInfo);
         mDrawable.setColorFilter(null);
         if (mCurrentColorAnim != null) {
             mCurrentColorAnim.cancel();
@@ -209,6 +210,9 @@
         setTextColor(mOriginalTextColor);
         (mHideParentOnDisable ? ((ViewGroup) getParent()) : this)
                 .setVisibility(mActive ? View.VISIBLE : View.GONE);
+
+        mAccessibleDrag = options.isAccessibleDrag;
+        setOnClickListener(mAccessibleDrag ? this : null);
     }
 
     @Override
@@ -227,6 +231,7 @@
     @Override
     public void onDragEnd() {
         mActive = false;
+        setOnClickListener(null);
     }
 
     /**
@@ -308,11 +313,6 @@
         return to;
     }
 
-    public void enableAccessibleDrag(boolean enable) {
-        mAccessibleDrag = enable;
-        setOnClickListener(enable ? this : null);
-    }
-
     @Override
     public void onClick(View v) {
         mLauncher.getAccessibilityDelegate().handleAccessibleDrop(this, null, null);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index baccfd1..6714d9f 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -236,6 +236,7 @@
         for (int i = 0; i < mDragOutlines.length; i++) {
             mDragOutlines[i] = new Rect(-1, -1, -1, -1);
         }
+        mDragOutlinePaint.setColor(getResources().getColor(R.color.outline_color));
 
         // When dragging things around the home screens, we show a green outline of
         // where the item will land. The outlines gradually fade out, leaving a trail
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index f24e00b..705f841 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -25,6 +25,7 @@
 import android.view.animation.AnimationUtils;
 
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.util.FlingAnimation;
 import com.android.launcher3.util.Thunk;
@@ -49,9 +50,9 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
-        super.onDragStart(source, info, dragAction);
-        setTextBasedOnDragSource(source);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        super.onDragStart(dragObject, options);
+        setTextBasedOnDragSource(dragObject.dragSource);
     }
 
     /** @return true for items that should have a "Remove" action in accessibility. */
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index e6802bd..c9fd85a 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -533,7 +533,6 @@
             } else {
                 // Put the page indicators above the hotseat
                 lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                lp.width = LayoutParams.WRAP_CONTENT;
                 lp.height = pageIndicatorHeightPx;
                 lp.bottomMargin = hotseatBarHeightPx + mInsets.bottom;
             }
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 5966af5..42bab47 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -27,6 +27,7 @@
 import android.widget.LinearLayout;
 
 import com.android.launcher3.dragndrop.DragController;
+import com.android.launcher3.dragndrop.DragOptions;
 
 /*
  * The top bar containing various drop targets: Delete/App Info/Uninstall.
@@ -120,17 +121,11 @@
         }
     }
 
-    public void enableAccessibleDrag(boolean enable) {
-        mDeleteDropTarget.enableAccessibleDrag(enable);
-        mAppInfoDropTarget.enableAccessibleDrag(enable);
-        mUninstallDropTarget.enableAccessibleDrag(enable);
-    }
-
     /*
      * DragController.DragListener implementation
      */
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         animateToVisibility(true);
     }
 
diff --git a/src/com/android/launcher3/HolographicOutlineHelper.java b/src/com/android/launcher3/HolographicOutlineHelper.java
index 6822311..9dec7d9 100644
--- a/src/com/android/launcher3/HolographicOutlineHelper.java
+++ b/src/com/android/launcher3/HolographicOutlineHelper.java
@@ -29,6 +29,10 @@
 import android.graphics.drawable.Drawable;
 import android.util.SparseArray;
 
+import com.android.launcher3.config.ProviderConfig;
+
+import java.nio.ByteBuffer;
+
 /**
  * Utility class to generate shadow and outline effect, which are used for click feedback
  * and drag-n-drop respectively.
@@ -79,50 +83,53 @@
      * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
      * bitmap.
      */
-    public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, true);
+    public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, true);
     }
 
-    public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor, boolean clipAlpha) {
+    public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas,
+            boolean clipAlpha) {
+        if (ProviderConfig.IS_DOGFOOD_BUILD && srcDst.getConfig() != Bitmap.Config.ALPHA_8) {
+            throw new RuntimeException("Outline blue is only supported on alpha bitmaps");
+        }
 
         // We start by removing most of the alpha channel so as to ignore shadows, and
         // other types of partial transparency when defining the shape of the object
         if (clipAlpha) {
-            int[] srcBuffer = new int[srcDst.getWidth() * srcDst.getHeight()];
-            srcDst.getPixels(srcBuffer,
-                    0, srcDst.getWidth(), 0, 0, srcDst.getWidth(), srcDst.getHeight());
-            for (int i = 0; i < srcBuffer.length; i++) {
-                final int alpha = srcBuffer[i] >>> 24;
-                if (alpha < 188) {
-                    srcBuffer[i] = 0;
+            byte[] pixels = new byte[srcDst.getWidth() * srcDst.getHeight()];
+            ByteBuffer buffer = ByteBuffer.wrap(pixels);
+            buffer.rewind();
+            srcDst.copyPixelsToBuffer(buffer);
+
+            for (int i = 0; i < pixels.length; i++) {
+                if ((pixels[i] & 0xFF) < 188) {
+                    pixels[i] = 0;
                 }
             }
-            srcDst.setPixels(srcBuffer,
-                    0, srcDst.getWidth(), 0, 0, srcDst.getWidth(), srcDst.getHeight());
+
+            buffer.rewind();
+            srcDst.copyPixelsFromBuffer(buffer);
         }
-        Bitmap glowShape = srcDst.extractAlpha();
 
         // calculate the outer blur first
         mBlurPaint.setMaskFilter(mMediumOuterBlurMaskFilter);
         int[] outerBlurOffset = new int[2];
-        Bitmap thickOuterBlur = glowShape.extractAlpha(mBlurPaint, outerBlurOffset);
+        Bitmap thickOuterBlur = srcDst.extractAlpha(mBlurPaint, outerBlurOffset);
 
         mBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter);
         int[] brightOutlineOffset = new int[2];
-        Bitmap brightOutline = glowShape.extractAlpha(mBlurPaint, brightOutlineOffset);
+        Bitmap brightOutline = srcDst.extractAlpha(mBlurPaint, brightOutlineOffset);
 
         // calculate the inner blur
-        srcDstCanvas.setBitmap(glowShape);
+        srcDstCanvas.setBitmap(srcDst);
         srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
         mBlurPaint.setMaskFilter(mMediumInnerBlurMaskFilter);
         int[] thickInnerBlurOffset = new int[2];
-        Bitmap thickInnerBlur = glowShape.extractAlpha(mBlurPaint, thickInnerBlurOffset);
+        Bitmap thickInnerBlur = srcDst.extractAlpha(mBlurPaint, thickInnerBlurOffset);
 
         // mask out the inner blur
         srcDstCanvas.setBitmap(thickInnerBlur);
-        srcDstCanvas.drawBitmap(glowShape, -thickInnerBlurOffset[0],
+        srcDstCanvas.drawBitmap(srcDst, -thickInnerBlurOffset[0],
                 -thickInnerBlurOffset[1], mErasePaint);
         srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(),
                 mErasePaint);
@@ -132,14 +139,12 @@
         // draw the inner and outer blur
         srcDstCanvas.setBitmap(srcDst);
         srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
-        mDrawPaint.setColor(color);
         srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
                 mDrawPaint);
         srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
                 mDrawPaint);
 
         // draw the bright outline
-        mDrawPaint.setColor(outlineColor);
         srcDstCanvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1],
                 mDrawPaint);
 
@@ -148,7 +153,6 @@
         brightOutline.recycle();
         thickOuterBlur.recycle();
         thickInnerBlur.recycle();
-        glowShape.recycle();
     }
 
     Bitmap createMediumDropShadow(BubbleTextView view) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index e136bcd..398c9d2 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -100,6 +100,7 @@
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1;
         return developmentSettingsEnabled
                 && (info instanceof AppInfo || info instanceof ShortcutInfo
-                || info instanceof PendingAddItemInfo || info instanceof LauncherAppWidgetInfo);
+                || info instanceof PendingAddItemInfo || info instanceof LauncherAppWidgetInfo)
+                && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
     }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index f5bcf5c..b628acf 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -35,7 +35,6 @@
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.DialogInterface;
@@ -102,6 +101,7 @@
 import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.dynamicui.ExtractedColors;
 import com.android.launcher3.folder.Folder;
@@ -115,10 +115,12 @@
 import com.android.launcher3.shortcuts.DeepShortcutsContainer;
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.util.ActivityResultInfo;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.MultiHashMap;
 import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.PendingRequestArgs;
 import com.android.launcher3.util.TestingUtils;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.util.ViewOnDrawExecutor;
@@ -183,12 +185,10 @@
     private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen";
     // Type: int
     private static final String RUNTIME_STATE = "launcher.state";
-    // Type: Content Values / parcelable
-    private static final String RUNTIME_STATE_PENDING_ADD_ITEM = "launcher.add_item";
-    // Type: parcelable
-    private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info";
-    // Type: parcelable
-    private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_ID = "launcher.add_widget_id";
+    // Type: PendingRequestArgs
+    private static final String RUNTIME_STATE_PENDING_REQUEST_ARGS = "launcher.request_args";
+    // Type: ActivityResultInfo
+    private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result";
 
     static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";
 
@@ -236,10 +236,6 @@
     private AppWidgetManagerCompat mAppWidgetManager;
     private LauncherAppWidgetHost mAppWidgetHost;
 
-    @Thunk final ItemInfo mPendingAddInfo = new ItemInfo();
-    private LauncherAppWidgetProviderInfo mPendingAddWidgetInfo;
-    private int mPendingAddWidgetId = -1;
-
     private int[] mTmpAddItemCellCoordinates = new int[2];
 
     @Thunk Hotseat mHotseat;
@@ -269,8 +265,6 @@
     @Thunk boolean mWorkspaceLoading = true;
 
     private boolean mPaused = true;
-    private boolean mRestoring;
-    private boolean mWaitingForResult;
     private boolean mOnResumeNeedsLoad;
 
     private ArrayList<Runnable> mBindOnResumeCallbacks = new ArrayList<Runnable>();
@@ -307,7 +301,6 @@
     private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500;
 
     private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>();
-    private static final boolean DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE = false;
 
     // We only want to get the SharedPreferences once since it does an FS stat each time we get
     // it from the context.
@@ -351,17 +344,13 @@
         }
     };
 
-    private static PendingAddArguments sPendingAddItem;
-
-    @Thunk static class PendingAddArguments {
-        int requestCode;
-        Intent intent;
-        long container;
-        long screenId;
-        int cellX;
-        int cellY;
-        int appWidgetId;
-    }
+    // Activity result which needs to be processed after workspace has loaded.
+    private ActivityResultInfo mPendingActivityResult;
+    /**
+     * Holds extra information required to handle a result from an external call, like
+     * {@link #startActivityForResult(Intent, int)} or {@link #requestPermissions(String[], int)}
+     */
+    private PendingRequestArgs mPendingRequestArgs;
 
     private UserEventDispatcher mUserEventDispatcher;
 
@@ -452,20 +441,14 @@
             Trace.endSection();
         }
 
-        if (!mRestoring) {
-            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
-                // If the user leaves launcher, then we should just load items asynchronously when
-                // they return.
-                mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
-            } else {
-                // We only load the page synchronously if the user rotates (or triggers a
-                // configuration change) while launcher is in the foreground
-                if (!mModel.startLoader(mWorkspace.getRestorePage())) {
-                    // If we are not binding synchronously, show a fade in animation when
-                    // the first page bind completes.
-                    mDragLayer.setAlpha(0);
-                }
-            }
+        // We only load the page synchronously if the user rotates (or triggers a
+        // configuration change) while launcher is in the foreground
+        if (!mModel.startLoader(mWorkspace.getRestorePage())) {
+            // If we are not binding synchronously, show a fade in animation when
+            // the first page bind completes.
+            mDragLayer.setAlpha(0);
+        } else {
+            setWorkspaceLoading(true);
         }
 
         // For handling default keys
@@ -658,53 +641,61 @@
      * Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
      * a configuration step, this allows the proper animations to run after other transitions.
      */
-    private long completeAdd(PendingAddArguments args) {
-        long screenId = args.screenId;
-        if (args.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+    private long completeAdd(
+            int requestCode, Intent intent, int appWidgetId, PendingRequestArgs info) {
+        long screenId = info.screenId;
+        if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
             // When the screen id represents an actual screen (as opposed to a rank) we make sure
             // that the drop page actually exists.
-            screenId = ensurePendingDropLayoutExists(args.screenId);
+            screenId = ensurePendingDropLayoutExists(info.screenId);
         }
 
-        switch (args.requestCode) {
+        switch (requestCode) {
             case REQUEST_CREATE_SHORTCUT:
-                completeAddShortcut(args.intent, args.container, screenId, args.cellX,
-                        args.cellY);
+                completeAddShortcut(intent, info.container, screenId, info.cellX, info.cellY);
                 break;
             case REQUEST_CREATE_APPWIDGET:
-                completeAddAppWidget(args.appWidgetId, args.container, screenId, null, null);
+                completeAddAppWidget(appWidgetId, info, null, null);
                 break;
             case REQUEST_RECONFIGURE_APPWIDGET:
-                completeRestoreAppWidget(args.appWidgetId, LauncherAppWidgetInfo.RESTORE_COMPLETED);
+                completeRestoreAppWidget(appWidgetId, LauncherAppWidgetInfo.RESTORE_COMPLETED);
                 break;
             case REQUEST_BIND_PENDING_APPWIDGET: {
-                int widgetId = args.appWidgetId;
-                LauncherAppWidgetInfo info =
+                int widgetId = appWidgetId;
+                LauncherAppWidgetInfo widgetInfo =
                         completeRestoreAppWidget(widgetId, LauncherAppWidgetInfo.FLAG_UI_NOT_READY);
-                if (info != null) {
+                if (widgetInfo != null) {
                     // Since the view was just bound, also launch the configure activity if needed
                     LauncherAppWidgetProviderInfo provider = mAppWidgetManager
                             .getLauncherAppWidgetInfo(widgetId);
                     if (provider != null && provider.configure != null) {
-                        startRestoredWidgetReconfigActivity(provider, info);
+                        startRestoredWidgetReconfigActivity(provider, widgetInfo);
                     }
                 }
                 break;
             }
         }
-        // Before adding this resetAddInfo(), after a shortcut was added to a workspace screen,
-        // if you turned the screen off and then back while in All Apps, Launcher would not
-        // return to the workspace. Clearing mAddInfo.container here fixes this issue
-        resetAddInfo();
+
         return screenId;
     }
 
     private void handleActivityResult(
             final int requestCode, final int resultCode, final Intent data) {
+        if (isWorkspaceLoading()) {
+            // process the result once the workspace has loaded.
+            mPendingActivityResult = new ActivityResultInfo(requestCode, resultCode, data);
+            return;
+        }
+        mPendingActivityResult = null;
+
         // Reset the startActivity waiting flag
-        setWaitingForResult(false);
-        final int pendingAddWidgetId = mPendingAddWidgetId;
-        mPendingAddWidgetId = -1;
+        final PendingRequestArgs requestArgs = mPendingRequestArgs;
+        setWaitingForResult(null);
+        if (requestArgs == null) {
+            return;
+        }
+
+        final int pendingAddWidgetId = requestArgs.getWidgetId();
 
         Runnable exitSpringLoaded = new Runnable() {
             @Override
@@ -719,12 +710,14 @@
             final int appWidgetId = data != null ?
                     data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
             if (resultCode == RESULT_CANCELED) {
-                completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
+                completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId, requestArgs);
                 mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
                         ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             } else if (resultCode == RESULT_OK) {
-                addAppWidgetImpl(appWidgetId, mPendingAddInfo, null,
-                        mPendingAddWidgetInfo, ON_ACTIVITY_RESULT_ANIMATION_DELAY);
+                addAppWidgetImpl(
+                        appWidgetId, requestArgs, null,
+                        requestArgs.getWidgetProvider(),
+                        ON_ACTIVITY_RESULT_ANIMATION_DELAY);
             }
             return;
         } else if (requestCode == REQUEST_PICK_WALLPAPER) {
@@ -740,7 +733,6 @@
         boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
                 requestCode == REQUEST_CREATE_APPWIDGET);
 
-        final boolean workspaceLocked = isWorkspaceLocked();
         // We have special handling for widgets
         if (isWidgetDrop) {
             final int appWidgetId;
@@ -757,46 +749,36 @@
                 Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not " +
                         "returned from the widget configuration activity.");
                 result = RESULT_CANCELED;
-                completeTwoStageWidgetDrop(result, appWidgetId);
+                completeTwoStageWidgetDrop(result, appWidgetId, requestArgs);
                 final Runnable onComplete = new Runnable() {
                     @Override
                     public void run() {
                         exitSpringLoadedDragModeDelayed(false, 0, null);
                     }
                 };
-                if (workspaceLocked) {
-                    // No need to remove the empty screen if we're mid-binding, as the
-                    // the bind will not add the empty screen.
-                    mWorkspace.postDelayed(onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY);
-                } else {
-                    mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
-                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
-                }
-            } else {
-                if (!workspaceLocked) {
-                    if (mPendingAddInfo.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                        // When the screen id represents an actual screen (as opposed to a rank)
-                        // we make sure that the drop page actually exists.
-                        mPendingAddInfo.screenId =
-                                ensurePendingDropLayoutExists(mPendingAddInfo.screenId);
-                    }
-                    final CellLayout dropLayout = mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
 
-                    dropLayout.setDropPending(true);
-                    final Runnable onComplete = new Runnable() {
-                        @Override
-                        public void run() {
-                            completeTwoStageWidgetDrop(resultCode, appWidgetId);
-                            dropLayout.setDropPending(false);
-                        }
-                    };
-                    mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
-                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
-                } else {
-                    PendingAddArguments args = preparePendingAddArgs(requestCode, data, appWidgetId,
-                            mPendingAddInfo);
-                    sPendingAddItem = args;
+                mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
+                        ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
+            } else {
+                if (requestArgs.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                    // When the screen id represents an actual screen (as opposed to a rank)
+                    // we make sure that the drop page actually exists.
+                    requestArgs.screenId =
+                            ensurePendingDropLayoutExists(requestArgs.screenId);
                 }
+                final CellLayout dropLayout =
+                        mWorkspace.getScreenWithId(requestArgs.screenId);
+
+                dropLayout.setDropPending(true);
+                final Runnable onComplete = new Runnable() {
+                    @Override
+                    public void run() {
+                        completeTwoStageWidgetDrop(resultCode, appWidgetId, requestArgs);
+                        dropLayout.setDropPending(false);
+                    }
+                };
+                mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
+                        ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             }
             return;
         }
@@ -805,13 +787,7 @@
                 || requestCode == REQUEST_BIND_PENDING_APPWIDGET) {
             if (resultCode == RESULT_OK) {
                 // Update the widget view.
-                PendingAddArguments args = preparePendingAddArgs(requestCode, data,
-                        pendingAddWidgetId, mPendingAddInfo);
-                if (workspaceLocked) {
-                    sPendingAddItem = args;
-                } else {
-                    completeAdd(args);
-                }
+                completeAdd(requestCode, data, pendingAddWidgetId, requestArgs);
             }
             // Leave the widget in the pending state if the user canceled the configure.
             return;
@@ -819,23 +795,17 @@
 
         if (requestCode == REQUEST_CREATE_SHORTCUT) {
             // Handle custom shortcuts created using ACTION_CREATE_SHORTCUT.
-            if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID) {
-                final PendingAddArguments args = preparePendingAddArgs(requestCode, data, -1,
-                        mPendingAddInfo);
-                if (isWorkspaceLocked()) {
-                    sPendingAddItem = args;
-                } else {
-                    completeAdd(args);
-                    mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
-                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
-                }
+            if (resultCode == RESULT_OK && requestArgs.container != ItemInfo.NO_ID) {
+                completeAdd(requestCode, data, -1, requestArgs);
+                mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
+                        ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
+
             } else if (resultCode == RESULT_CANCELED) {
                 mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
                         ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             }
         }
         mDragLayer.clearAnimatedView();
-
     }
 
     @Override
@@ -850,15 +820,18 @@
     /** @Override for MNC */
     public void onRequestPermissionsResult(int requestCode, String[] permissions,
             int[] grantResults) {
-        if (requestCode == REQUEST_PERMISSION_CALL_PHONE && sPendingAddItem != null
-                && sPendingAddItem.requestCode == REQUEST_PERMISSION_CALL_PHONE) {
+        PendingRequestArgs pendingArgs = mPendingRequestArgs;
+        if (requestCode == REQUEST_PERMISSION_CALL_PHONE && pendingArgs != null
+                && pendingArgs.getRequestCode() == REQUEST_PERMISSION_CALL_PHONE) {
+            setWaitingForResult(null);
+
             View v = null;
-            CellLayout layout = getCellLayout(sPendingAddItem.container, sPendingAddItem.screenId);
+            CellLayout layout = getCellLayout(pendingArgs.container, pendingArgs.screenId);
             if (layout != null) {
-                v = layout.getChildAt(sPendingAddItem.cellX, sPendingAddItem.cellY);
+                v = layout.getChildAt(pendingArgs.cellX, pendingArgs.cellY);
             }
-            Intent intent = sPendingAddItem.intent;
-            sPendingAddItem = null;
+            Intent intent = pendingArgs.getPendingIntent();
+
             if (grantResults.length > 0
                     && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                 startActivitySafely(v, intent, null);
@@ -874,19 +847,6 @@
         }
     }
 
-    private PendingAddArguments preparePendingAddArgs(int requestCode, Intent data, int
-            appWidgetId, ItemInfo info) {
-        PendingAddArguments args = new PendingAddArguments();
-        args.requestCode = requestCode;
-        args.intent = data;
-        args.container = info.container;
-        args.screenId = info.screenId;
-        args.cellX = info.cellX;
-        args.cellY = info.cellY;
-        args.appWidgetId = appWidgetId;
-        return args;
-    }
-
     /**
      * Check to see if a given screen id exists. If not, create it at the end, return the new id.
      *
@@ -905,8 +865,9 @@
         }
     }
 
-    @Thunk void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
-        CellLayout cellLayout = mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
+    @Thunk void completeTwoStageWidgetDrop(
+            final int resultCode, final int appWidgetId, final PendingRequestArgs requestArgs) {
+        CellLayout cellLayout = mWorkspace.getScreenWithId(requestArgs.screenId);
         Runnable onCompleteRunnable = null;
         int animationType = 0;
 
@@ -914,13 +875,12 @@
         if (resultCode == RESULT_OK) {
             animationType = Workspace.COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION;
             final AppWidgetHostView layout = mAppWidgetHost.createView(this, appWidgetId,
-                    mPendingAddWidgetInfo);
+                    requestArgs.getWidgetProvider());
             boundWidget = layout;
             onCompleteRunnable = new Runnable() {
                 @Override
                 public void run() {
-                    completeAddAppWidget(appWidgetId, mPendingAddInfo.container,
-                            mPendingAddInfo.screenId, layout, null);
+                    completeAddAppWidget(appWidgetId, requestArgs, layout, null);
                     exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
                             EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
                 }
@@ -930,7 +890,7 @@
             animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION;
         }
         if (mDragLayer.getAnimatedView() != null) {
-            mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout,
+            mWorkspace.animateWidgetDrop(requestArgs, cellLayout,
                     (DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
                     animationType, boundWidget, true);
         } else if (onCompleteRunnable != null) {
@@ -998,10 +958,9 @@
         mOnResumeState = State.NONE;
 
         mPaused = false;
-        if (mRestoring || mOnResumeNeedsLoad) {
+        if (mOnResumeNeedsLoad) {
             setWorkspaceLoading(true);
             mModel.startLoader(getCurrentWorkspaceScreen());
-            mRestoring = false;
             mOnResumeNeedsLoad = false;
         }
         if (mBindOnResumeCallbacks.size() > 0) {
@@ -1316,18 +1275,12 @@
             mWorkspace.setRestorePage(currentScreen);
         }
 
-        ContentValues itemValues = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_ITEM);
-        if (itemValues != null) {
-            mPendingAddInfo.readFromValues(itemValues);
-            AppWidgetProviderInfo info = savedState.getParcelable(
-                    RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
-            mPendingAddWidgetInfo = info == null ?
-                    null : LauncherAppWidgetProviderInfo.fromProviderInfo(this, info);
-
-            mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID);
-            setWaitingForResult(true);
-            mRestoring = true;
+        PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS);
+        if (requestArgs != null) {
+            setWaitingForResult(requestArgs);
         }
+
+        mPendingActivityResult = savedState.getParcelable(RUNTIME_STATE_PENDING_ACTIVITY_RESULT);
     }
 
     /**
@@ -1542,10 +1495,8 @@
 
         LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1]);
 
-        if (!mRestoring) {
-            mWorkspace.addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1,
-                    isWorkspaceLocked());
-        }
+        mWorkspace.addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1,
+                isWorkspaceLocked());
     }
 
     /**
@@ -1553,10 +1504,9 @@
      *
      * @param appWidgetId The app widget id
      */
-    @Thunk void completeAddAppWidget(int appWidgetId, long container, long screenId,
+    @Thunk void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
             AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) {
 
-        ItemInfo info = mPendingAddInfo;
         if (appWidgetInfo == null) {
             appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
         }
@@ -1567,24 +1517,21 @@
 
         LauncherAppWidgetInfo launcherInfo;
         launcherInfo = new LauncherAppWidgetInfo(appWidgetId, appWidgetInfo.provider);
-        launcherInfo.spanX = info.spanX;
-        launcherInfo.spanY = info.spanY;
-        launcherInfo.minSpanX = info.minSpanX;
-        launcherInfo.minSpanY = info.minSpanY;
+        launcherInfo.spanX = itemInfo.spanX;
+        launcherInfo.spanY = itemInfo.spanY;
+        launcherInfo.minSpanX = itemInfo.minSpanX;
+        launcherInfo.minSpanY = itemInfo.minSpanY;
         launcherInfo.user = mAppWidgetManager.getUser(appWidgetInfo);
 
         LauncherModel.addItemToDatabase(this, launcherInfo,
-                container, screenId, info.cellX, info.cellY);
+                itemInfo.container, itemInfo.screenId, itemInfo.cellX, itemInfo.cellY);
 
-        if (!mRestoring) {
-            if (hostView == null) {
-                // Perform actual inflation because we're live
-                hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
-            }
-            hostView.setVisibility(View.VISIBLE);
-            addAppWidgetToWorkspace(hostView, launcherInfo, appWidgetInfo, isWorkspaceLocked());
+        if (hostView == null) {
+            // Perform actual inflation because we're live
+            hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
         }
-        resetAddInfo();
+        hostView.setVisibility(View.VISIBLE);
+        addAppWidgetToWorkspace(hostView, launcherInfo, appWidgetInfo, isWorkspaceLocked());
     }
 
     private void addAppWidgetToWorkspace(
@@ -1615,8 +1562,7 @@
 
                 // Reset AllApps to its initial state only if we are not in the middle of
                 // processing a multi-step drop
-                if (mAppsView != null && mWidgetsView != null &&
-                        mPendingAddInfo.container == ItemInfo.NO_ID) {
+                if (mAppsView != null && mWidgetsView != null && mPendingRequestArgs == null) {
                     if (!showWorkspace(false)) {
                         // If we are already on the workspace, then manually reset all apps
                         mAppsView.reset();
@@ -1828,7 +1774,7 @@
         getWindow().closeAllPanels();
 
         // Whatever we were doing is hereby canceled.
-        setWaitingForResult(false);
+        setWaitingForResult(null);
     }
 
     @Override
@@ -1946,13 +1892,11 @@
         closeFolder(false);
         closeShortcutsContainer(false);
 
-        if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screenId > -1 &&
-                mWaitingForResult) {
-            ContentValues itemValues = new ContentValues();
-            mPendingAddInfo.writeToValues(itemValues);
-            outState.putParcelable(RUNTIME_STATE_PENDING_ADD_ITEM, itemValues);
-            outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo);
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId);
+        if (mPendingRequestArgs != null) {
+            outState.putParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS, mPendingRequestArgs);
+        }
+        if (mPendingActivityResult != null) {
+            outState.putParcelable(RUNTIME_STATE_PENDING_ACTIVITY_RESULT, mPendingActivityResult);
         }
 
         if (mLauncherCallbacks != null) {
@@ -2015,14 +1959,12 @@
 
     @Override
     public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
-        onStartForResult(requestCode);
         super.startActivityForResult(intent, requestCode, options);
     }
 
     @Override
     public void startIntentSenderForResult (IntentSender intent, int requestCode,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
-        onStartForResult(requestCode);
         try {
             super.startIntentSenderForResult(intent, requestCode,
                 fillInIntent, flagsMask, flagsValues, extraFlags, options);
@@ -2031,12 +1973,6 @@
         }
     }
 
-    private void onStartForResult(int requestCode) {
-        if (requestCode >= 0) {
-            setWaitingForResult(true);
-        }
-    }
-
     /**
      * Indicates that we want global search for this activity by setting the globalSearch
      * argument for {@link #startSearch} to true.
@@ -2147,7 +2083,7 @@
     }
 
     public boolean isWorkspaceLocked() {
-        return mWorkspaceLoading || mWaitingForResult;
+        return mWorkspaceLoading || mPendingRequestArgs != null;
     }
 
     public boolean isWorkspaceLoading() {
@@ -2162,9 +2098,9 @@
         }
     }
 
-    private void setWaitingForResult(boolean value) {
+    private void setWaitingForResult(PendingRequestArgs args) {
         boolean isLocked = isWorkspaceLocked();
-        mWaitingForResult = value;
+        mPendingRequestArgs = args;
         if (isLocked != isWorkspaceLocked()) {
             onWorkspaceLockedChanged();
         }
@@ -2176,33 +2112,23 @@
         }
     }
 
-    private void resetAddInfo() {
-        mPendingAddInfo.container = ItemInfo.NO_ID;
-        mPendingAddInfo.screenId = -1;
-        mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
-        mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
-        mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = 1;
-    }
-
-    void addAppWidgetFromDropImpl(final int appWidgetId, final ItemInfo info, final
-            AppWidgetHostView boundWidget, final LauncherAppWidgetProviderInfo appWidgetInfo) {
+    void addAppWidgetFromDropImpl(int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget,
+            LauncherAppWidgetProviderInfo appWidgetInfo) {
         if (LOGD) {
             Log.d(TAG, "Adding widget from drop");
         }
         addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0);
     }
 
-    void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
-            final AppWidgetHostView boundWidget, final LauncherAppWidgetProviderInfo appWidgetInfo,
+    void addAppWidgetImpl(int appWidgetId, ItemInfo info,
+            AppWidgetHostView boundWidget, LauncherAppWidgetProviderInfo appWidgetInfo,
             int delay) {
         if (appWidgetInfo.configure != null) {
-            mPendingAddWidgetInfo = appWidgetInfo;
-            mPendingAddWidgetId = appWidgetId;
+            setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, appWidgetInfo, info));
 
             // Launch over to configure widget, if needed
             mAppWidgetManager.startConfigActivity(appWidgetInfo, appWidgetId, this,
                     mAppWidgetHost, REQUEST_CREATE_APPWIDGET);
-
         } else {
             // Otherwise just add it
             Runnable onComplete = new Runnable() {
@@ -2213,8 +2139,7 @@
                             null);
                 }
             };
-            completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
-                    appWidgetInfo);
+            completeAddAppWidget(appWidgetId, info, boundWidget, appWidgetInfo);
             mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
         }
     }
@@ -2227,17 +2152,22 @@
 
     public void addPendingItem(PendingAddItemInfo info, long container, long screenId,
             int[] cell, int spanX, int spanY) {
+        info.container = container;
+        info.screenId = screenId;
+        if (cell != null) {
+            info.cellX = cell[0];
+            info.cellY = cell[1];
+        }
+        info.spanX = spanX;
+        info.spanY = spanY;
+
         switch (info.itemType) {
             case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
-                int span[] = new int[2];
-                span[0] = spanX;
-                span[1] = spanY;
-                addAppWidgetFromDrop((PendingAddWidgetInfo) info,
-                        container, screenId, cell, span);
+                addAppWidgetFromDrop((PendingAddWidgetInfo) info);
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
-                processShortcutFromDrop(info.componentName, container, screenId, cell);
+                processShortcutFromDrop(info);
                 break;
             default:
                 throw new IllegalStateException("Unknown item type: " + info.itemType);
@@ -2246,51 +2176,18 @@
 
     /**
      * Process a shortcut drop.
-     *
-     * @param componentName The name of the component
-     * @param screenId The ID of the screen where it should be added
-     * @param cell The cell it should be added to, optional
      */
-    private void processShortcutFromDrop(ComponentName componentName, long container, long screenId,
-            int[] cell) {
-        resetAddInfo();
-        mPendingAddInfo.container = container;
-        mPendingAddInfo.screenId = screenId;
-
-        if (cell != null) {
-            mPendingAddInfo.cellX = cell[0];
-            mPendingAddInfo.cellY = cell[1];
-        }
-
+    private void processShortcutFromDrop(PendingAddItemInfo info) {
+        setWaitingForResult(new PendingRequestArgs(info));
         Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
-        createShortcutIntent.setComponent(componentName);
+        createShortcutIntent.setComponent(info.componentName);
         Utilities.startActivityForResultSafely(this, createShortcutIntent, REQUEST_CREATE_SHORTCUT);
     }
 
     /**
      * Process a widget drop.
-     *
-     * @param info The PendingAppWidgetInfo of the widget being added.
-     * @param screenId The ID of the screen where it should be added
-     * @param cell The cell it should be added to, optional
      */
-    private void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId,
-            int[] cell, int[] span) {
-        resetAddInfo();
-        mPendingAddInfo.container = info.container = container;
-        mPendingAddInfo.screenId = info.screenId = screenId;
-        mPendingAddInfo.minSpanX = info.minSpanX;
-        mPendingAddInfo.minSpanY = info.minSpanY;
-
-        if (cell != null) {
-            mPendingAddInfo.cellX = cell[0];
-            mPendingAddInfo.cellY = cell[1];
-        }
-        if (span != null) {
-            mPendingAddInfo.spanX = span[0];
-            mPendingAddInfo.spanY = span[1];
-        }
-
+    private void addAppWidgetFromDrop(PendingAddWidgetInfo info) {
         AppWidgetHostView hostView = info.boundWidget;
         int appWidgetId;
         if (hostView != null) {
@@ -2316,11 +2213,11 @@
             if (success) {
                 addAppWidgetFromDropImpl(appWidgetId, info, null, info.info);
             } else {
-                mPendingAddWidgetInfo = info.info;
+                setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, info.info, info));
                 Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
                 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
-                mAppWidgetManager.getUser(mPendingAddWidgetInfo)
+                mAppWidgetManager.getUser(info.info)
                     .addToIntent(intent, AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
                 // TODO: we need to make sure that this accounts for the options bundle.
                 // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
@@ -2539,14 +2436,13 @@
                 LauncherAppWidgetProviderInfo appWidgetInfo =
                         mAppWidgetManager.findProvider(info.providerName, info.user);
                 if (appWidgetInfo != null) {
-                    mPendingAddWidgetId = info.appWidgetId;
-                    mPendingAddInfo.copyFrom(info);
-                    mPendingAddWidgetInfo = appWidgetInfo;
+                    setWaitingForResult(PendingRequestArgs
+                            .forWidgetInfo(info.appWidgetId, appWidgetInfo, info));
 
                     Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
-                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingAddWidgetId);
+                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, info.appWidgetId);
                     intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, appWidgetInfo.provider);
-                    mAppWidgetManager.getUser(mPendingAddWidgetInfo)
+                    mAppWidgetManager.getUser(appWidgetInfo)
                             .addToIntent(intent, AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
                     startActivityForResult(intent, REQUEST_BIND_PENDING_APPWIDGET);
                 }
@@ -2575,9 +2471,7 @@
 
     private void startRestoredWidgetReconfigActivity(
             LauncherAppWidgetProviderInfo provider, LauncherAppWidgetInfo info) {
-        mPendingAddWidgetInfo = provider;
-        mPendingAddInfo.copyFrom(info);
-        mPendingAddWidgetId = info.appWidgetId;
+        setWaitingForResult(PendingRequestArgs.forWidgetInfo(info.appWidgetId, provider, info));
         mAppWidgetManager.startConfigActivity(provider,
                 info.appWidgetId, this, mAppWidgetHost, REQUEST_RECONFIGURE_APPWIDGET);
     }
@@ -2747,6 +2641,7 @@
         int pageScroll = mWorkspace.getScrollForPage(mWorkspace.getPageNearestToCenterOfScreen());
         float offset = mWorkspace.mWallpaperOffset.wallpaperOffsetForScroll(pageScroll);
 
+        setWaitingForResult(new PendingRequestArgs(new ItemInfo()));
         Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
                 .setPackage(pickerPackage)
                 .putExtra(Utilities.EXTRA_WALLPAPER_OFFSET, offset);
@@ -2863,9 +2758,9 @@
                     && Intent.ACTION_CALL.equals(intent.getAction())
                     && checkSelfPermission(Manifest.permission.CALL_PHONE) !=
                     PackageManager.PERMISSION_GRANTED) {
-                // TODO: Rename sPendingAddItem to a generic name.
-                sPendingAddItem = preparePendingAddArgs(REQUEST_PERMISSION_CALL_PHONE, intent,
-                        0, info);
+
+                setWaitingForResult(PendingRequestArgs
+                        .forIntent(REQUEST_PERMISSION_CALL_PHONE, intent, info));
                 requestPermissions(new String[]{Manifest.permission.CALL_PHONE},
                         REQUEST_PERMISSION_CALL_PHONE);
             } else {
@@ -3150,6 +3045,14 @@
         }
     }
 
+    public View getTopFloatingView() {
+        View topView = getOpenShortcutsContainer();
+        if (topView == null) {
+            topView = getWorkspace().getOpenFolder();
+        }
+        return topView;
+    }
+
     /**
      * @return The open shortcuts container, or null if there is none
      */
@@ -3199,7 +3102,7 @@
             ItemInfo info = (ItemInfo) v.getTag();
             longClickCellInfo = new CellLayout.CellInfo(v, info);
             itemUnderLongClick = longClickCellInfo.cell;
-            resetAddInfo();
+            mPendingRequestArgs = null;
         }
 
         // The hotseat touch handling does not go through Workspace, and we always allow long press
@@ -3222,7 +3125,7 @@
                                         longClickCellInfo.cellX, longClickCellInfo.cellY));
                 if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) {
                     // User long pressed on an item
-                    mWorkspace.startDrag(longClickCellInfo);
+                    mWorkspace.startDrag(longClickCellInfo, new DragOptions());
                 }
             }
         }
@@ -4074,21 +3977,10 @@
 
         setWorkspaceLoading(false);
 
-        // If we received the result of any pending adds while the loader was running (e.g. the
-        // widget configuration forced an orientation change), process them now.
-        if (sPendingAddItem != null) {
-            final long screenId = completeAdd(sPendingAddItem);
-
-            // TODO: this moves the user to the page where the pending item was added. Ideally,
-            // the screen would be guaranteed to exist after bind, and the page would be set through
-            // the workspace restore process.
-            mWorkspace.post(new Runnable() {
-                @Override
-                public void run() {
-                    mWorkspace.snapToScreenId(screenId);
-                }
-            });
-            sPendingAddItem = null;
+        if (mPendingActivityResult != null) {
+            handleActivityResult(mPendingActivityResult.requestCode,
+                    mPendingActivityResult.resultCode, mPendingActivityResult.data);
+            mPendingActivityResult = null;
         }
 
         InstallShortcutReceiver.disableAndFlushInstallQueue(this);
@@ -4504,8 +4396,8 @@
         Log.d(TAG, "BEGIN launcher3 dump state for launcher " + this);
         Log.d(TAG, "mSavedState=" + mSavedState);
         Log.d(TAG, "mWorkspaceLoading=" + mWorkspaceLoading);
-        Log.d(TAG, "mRestoring=" + mRestoring);
-        Log.d(TAG, "mWaitingForResult=" + mWaitingForResult);
+        Log.d(TAG, "mPendingRequestArgs=" + mPendingRequestArgs);
+        Log.d(TAG, "mPendingActivityResult=" + mPendingActivityResult);
         mModel.dumpState();
         // TODO(hyunyoungs): add mWidgetsView.dumpState(); or mWidgetsModel.dumpState();
 
diff --git a/src/com/android/launcher3/PinchToOverviewListener.java b/src/com/android/launcher3/PinchToOverviewListener.java
index 6ee96fc..48a75d1 100644
--- a/src/com/android/launcher3/PinchToOverviewListener.java
+++ b/src/com/android/launcher3/PinchToOverviewListener.java
@@ -102,8 +102,8 @@
             // once the state switching animation is complete.
             return false;
         }
-        if (mWorkspace.getOpenFolder() != null) {
-            // Don't listen for the pinch gesture if a folder is open.
+        if (mLauncher.getTopFloatingView() != null) {
+            // Don't listen for the pinch gesture if a floating view is open.
             return false;
         }
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index f2cf120..e34f509 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -58,6 +58,8 @@
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
 import com.android.launcher3.compat.UserHandleCompat;
@@ -906,4 +908,15 @@
         ta.recycle();
         return colorAccent;
     }
+
+    public static void sendCustomAccessibilityEvent(View target, int type, String text) {
+        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                target.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager.isEnabled()) {
+            AccessibilityEvent event = AccessibilityEvent.obtain(type);
+            target.onInitializeAccessibilityEvent(event);
+            event.getText().add(text);
+            accessibilityManager.sendAccessibilityEvent(event);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 66745ab..d5f1363 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -59,7 +59,7 @@
 import com.android.launcher3.Launcher.CustomContentCallbacks;
 import com.android.launcher3.Launcher.LauncherOverlay;
 import com.android.launcher3.UninstallDropTarget.DropTargetSource;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.accessibility.AccessibileDragListenerAdapter;
 import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
 import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
@@ -69,6 +69,7 @@
 import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragScroller;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.dragndrop.SpringLoadedDragController;
@@ -100,7 +101,7 @@
 public class Workspace extends PagedView
         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
         DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
-        Insettable, DropTargetSource, AccessibilityDragSource {
+        Insettable, DropTargetSource {
     private static final String TAG = "Launcher.Workspace";
 
     private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
@@ -134,7 +135,6 @@
 
     @Thunk Runnable mRemoveEmptyScreenRunnable;
     @Thunk boolean mDeferRemoveExtraEmptyScreen = false;
-    @Thunk boolean mAddNewPageOnDrag = true;
 
     /**
      * CellInfo for the cell that is currently being dragged
@@ -409,7 +409,7 @@
     }
 
     @Override
-    public void onDragStart(final DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         if (ENFORCE_DRAG_EVENT_ORDER) {
             enfoceDragParity("onDragStart", 0, 0);
         }
@@ -426,11 +426,19 @@
         // Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
         InstallShortcutReceiver.enableInstallQueue();
 
-        if (mAddNewPageOnDrag) {
+        // Do not add a new page if it is a accessible drag which was not started by the workspace.
+        // We do not support accessibility drag from other sources and instead provide a direct
+        // action for move/add to homescreen.
+        // When a accessible drag is started by the folder, we only allow rearranging withing the
+        // folder.
+        boolean addNewPage = !(options.isAccessibleDrag && dragObject.dragSource != this);
+
+        if (addNewPage) {
             mDeferRemoveExtraEmptyScreen = false;
             addExtraEmptyScreenOnDrag();
 
-            if (source != this && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+            if (dragObject.dragInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+                    && dragObject.dragSource != this) {
                 // When dragging a widget from different source, move to a page which has
                 // enough space to place this widget (after rearranging/resizing). We special case
                 // widgets as they cannot be placed inside a folder.
@@ -439,7 +447,7 @@
                 int currentPage = getPageNearestToCenterOfScreen();
                 for (int pageIndex = currentPage; pageIndex < getPageCount(); pageIndex++) {
                     CellLayout page = (CellLayout) getPageAt(pageIndex);
-                    if (page.hasReorderSolution(info)) {
+                    if (page.hasReorderSolution(dragObject.dragInfo)) {
                         setCurrentPage(pageIndex);
                         break;
                     }
@@ -453,10 +461,6 @@
         }
     }
 
-    public void setAddNewPageOnDrag(boolean addPage) {
-        mAddNewPageOnDrag = addPage;
-    }
-
     public void deferRemoveExtraEmptyScreen() {
         mDeferRemoveExtraEmptyScreen = true;
     }
@@ -1722,26 +1726,6 @@
         }
     }
 
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @Override
-    public void enableAccessibleDrag(boolean enable) {
-        for (int i = 0; i < getChildCount(); i++) {
-            CellLayout child = (CellLayout) getChildAt(i);
-            child.enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-        }
-
-        if (enable) {
-            // We need to allow our individual children to become click handlers in this case
-            setOnClickListener(null);
-        } else {
-            // Reset our click listener
-            setOnClickListener(mLauncher);
-        }
-        mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
-        mLauncher.getHotseat().getLayout()
-            .enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
-    }
-
     public boolean hasCustomContent() {
         return (mScreenOrder.size() > 0 && mScreenOrder.get(0) == CUSTOM_CONTENT_SCREEN_ID);
     }
@@ -1874,19 +1858,6 @@
     }
 
     @Override
-    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        if (!mLauncher.isAppsViewVisible()) {
-            final Folder openFolder = getOpenFolder();
-            if (openFolder != null) {
-                return openFolder.requestFocus(direction, previouslyFocusedRect);
-            } else {
-                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
-            }
-        }
-        return false;
-    }
-
-    @Override
     public int getDescendantFocusability() {
         if (workspaceInModalState()) {
             return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
@@ -1894,18 +1865,6 @@
         return super.getDescendantFocusability();
     }
 
-    @Override
-    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if (!mLauncher.isAppsViewVisible()) {
-            final Folder openFolder = getOpenFolder();
-            if (openFolder != null) {
-                openFolder.addFocusables(views, direction);
-            } else {
-                super.addFocusables(views, direction, focusableMode);
-            }
-        }
-    }
-
     public boolean workspaceInModalState() {
         return mState != State.NORMAL;
     }
@@ -2280,12 +2239,7 @@
         return null;
     }
 
-    public void startDrag(CellLayout.CellInfo cellInfo) {
-        startDrag(cellInfo, false);
-    }
-
-    @Override
-    public void startDrag(CellLayout.CellInfo cellInfo, boolean accessible) {
+    public void startDrag(CellLayout.CellInfo cellInfo, DragOptions options) {
         View child = cellInfo.cell;
 
         // Make sure the drag was started by a long press as opposed to a long click.
@@ -2298,10 +2252,25 @@
         CellLayout layout = (CellLayout) child.getParent().getParent();
         layout.prepareChildForDrag(child);
 
-        beginDragShared(child, this, accessible);
+        if (options.isAccessibleDrag) {
+            mDragController.addDragListener(new AccessibileDragListenerAdapter(
+                    this, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG) {
+                @Override
+                protected void enableAccessibleDrag(boolean enable) {
+                    super.enableAccessibleDrag(enable);
+                    setEnableForLayout(mLauncher.getHotseat().getLayout(),enable);
+
+                    // We need to allow our individual children to become click handlers in this
+                    // case, so temporarily unset the click handlers.
+                    setOnClickListener(enable ? null : mLauncher);
+                }
+            });
+        }
+
+        beginDragShared(child, this, options);
     }
 
-    public void beginDragShared(View child, DragSource source, boolean accessible) {
+    public void beginDragShared(View child, DragSource source, DragOptions options) {
         Object dragObject = child.getTag();
         if (!(dragObject instanceof ItemInfo)) {
             String msg = "Drag started with a view that has no tag set. This "
@@ -2309,13 +2278,13 @@
                     + "View: " + child + "  tag: " + child.getTag();
             throw new IllegalStateException(msg);
         }
-        beginDragShared(child, source, accessible, (ItemInfo) dragObject,
-                new DragPreviewProvider(child));
+        beginDragShared(child, source, (ItemInfo) dragObject,
+                new DragPreviewProvider(child), options);
     }
 
 
-    public DragView beginDragShared(View child, DragSource source, boolean accessible,
-            ItemInfo dragObject, DragPreviewProvider previewProvider) {
+    public DragView beginDragShared(View child, DragSource source, ItemInfo dragObject,
+            DragPreviewProvider previewProvider, DragOptions dragOptions) {
         child.clearFocus();
         child.setPressed(false);
         mOutlineProvider = previewProvider;
@@ -2359,8 +2328,7 @@
         }
 
         DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
-                dragObject, DragController.DRAG_ACTION_MOVE, dragVisualizeOffset,
-                dragRect, scale, accessible);
+                dragObject, dragVisualizeOffset, dragRect, scale, dragOptions);
         dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
         b.recycle();
         return dv;
diff --git a/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java b/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java
new file mode 100644
index 0000000..62a9a6d
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/AccessibileDragListenerAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.accessibility;
+
+import android.view.ViewGroup;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.dragndrop.DragController.DragListener;
+import com.android.launcher3.dragndrop.DragOptions;
+
+/**
+ * Utility listener to enable/disable accessibility drag flags for a ViewGroup
+ * containing CellLayouts
+ */
+public class AccessibileDragListenerAdapter implements DragListener {
+
+    private final ViewGroup mViewGroup;
+    private final int mDragType;
+
+    /**
+     * @param parent
+     * @param dragType either {@link CellLayout#WORKSPACE_ACCESSIBILITY_DRAG} or
+     *                 {@link CellLayout#FOLDER_ACCESSIBILITY_DRAG}
+     */
+    public AccessibileDragListenerAdapter(ViewGroup parent, int dragType) {
+        mViewGroup = parent;
+        mDragType = dragType;
+    }
+
+    @Override
+    public void onDragStart(DragObject dragObject, DragOptions options) {
+        enableAccessibleDrag(true);
+    }
+
+    @Override
+    public void onDragEnd() {
+        enableAccessibleDrag(false);
+        Launcher.getLauncher(mViewGroup.getContext()).getDragController().removeDragListener(this);
+    }
+
+    protected void enableAccessibleDrag(boolean enable) {
+        for (int i = 0; i < mViewGroup.getChildCount(); i++) {
+            setEnableForLayout((CellLayout) mViewGroup.getChildAt(i), enable);
+        }
+    }
+
+    protected final void setEnableForLayout(CellLayout layout, boolean enable) {
+        layout.enableAccessibleDrag(enable, mDragType);
+    }
+}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 0562cf5..173aad0 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -22,6 +22,8 @@
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeleteDropTarget;
 import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.FolderInfo;
 import com.android.launcher3.InfoDropTarget;
@@ -73,7 +75,6 @@
     @Thunk final Launcher mLauncher;
 
     private DragInfo mDragInfo = null;
-    private AccessibilityDragSource mDragSource = null;
 
     public LauncherAccessibilityDelegate(Launcher launcher) {
         mLauncher = launcher;
@@ -372,26 +373,25 @@
 
         Folder folder = workspace.getOpenFolder();
         if (folder != null) {
-            if (folder.getItemsInReadingOrder().contains(item)) {
-                mDragSource = folder;
-            } else {
+            if (!folder.getItemsInReadingOrder().contains(item)) {
                 mLauncher.closeFolder();
+                folder = null;
             }
         }
-        if (mDragSource == null) {
-            mDragSource = workspace;
-        }
-        mDragSource.enableAccessibleDrag(true);
-        mDragSource.startDrag(cellInfo, true);
 
-        if (mLauncher.getDragController().isDragging()) {
-            mLauncher.getDragController().addDragListener(this);
+        mLauncher.getDragController().addDragListener(this);
+
+        DragOptions options = new DragOptions();
+        options.isAccessibleDrag = true;
+        if (folder != null) {
+            folder.startDrag(cellInfo.cell, options);
+        } else {
+            workspace.startDrag(cellInfo, options);
         }
     }
 
-
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DragObject dragObject, DragOptions options) {
         // No-op
     }
 
@@ -399,16 +399,6 @@
     public void onDragEnd() {
         mLauncher.getDragController().removeDragListener(this);
         mDragInfo = null;
-        if (mDragSource != null) {
-            mDragSource.enableAccessibleDrag(false);
-            mDragSource = null;
-        }
-    }
-
-    public static interface AccessibilityDragSource {
-        void startDrag(CellLayout.CellInfo cellInfo, boolean accessible);
-
-        void enableAccessibleDrag(boolean enable);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java b/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
index dafa73f..cfd07e6 100644
--- a/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
+++ b/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
@@ -96,14 +96,14 @@
     public AllAppsBackgroundDrawable(Context context) {
         Resources res = context.getResources();
         mHand = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_hand,
-                0.575f, 0.1f, Gravity.CENTER_HORIZONTAL);
+                0.575f, 0.f, Gravity.CENTER_HORIZONTAL);
         mIcons = new TransformedImageDrawable[4];
         mIcons[0] = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_icon_1,
                 0.375f, 0, Gravity.CENTER_HORIZONTAL);
         mIcons[1] = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_icon_2,
-                0.3125f, 0.25f, Gravity.CENTER_HORIZONTAL);
+                0.3125f, 0.2f, Gravity.CENTER_HORIZONTAL);
         mIcons[2] = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_icon_3,
-                0.475f, 0.4f, Gravity.CENTER_HORIZONTAL);
+                0.475f, 0.26f, Gravity.CENTER_HORIZONTAL);
         mIcons[3] = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_icon_4,
                 0.7f, 0.125f, Gravity.CENTER_HORIZONTAL);
         mWidth = res.getDimensionPixelSize(R.dimen.all_apps_background_canvas_width);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 4e1936f..0a71a69 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -49,6 +49,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.graphics.TintedDrawableSpan;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
@@ -539,7 +540,7 @@
         if (!mLauncher.isDraggingEnabled()) return false;
 
         // Start the drag
-        mLauncher.getWorkspace().beginDragShared(v, this, false);
+        mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions());
         // Enter spring loaded mode
         mLauncher.enterSpringLoadedDragMode();
 
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index b57f5bf..29e33e9 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -57,12 +57,6 @@
 public class DragController implements DragDriver.EventListener, TouchController {
     private static final String TAG = "Launcher.DragController";
 
-    /** Indicates the drag is a move.  */
-    public static int DRAG_ACTION_MOVE = 0;
-
-    /** Indicates the drag is a copy.  */
-    public static int DRAG_ACTION_COPY = 1;
-
     public static final int SCROLL_DELAY = 500;
     public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
 
@@ -91,8 +85,8 @@
      */
     private DragDriver mDragDriver = null;
 
-    /** Whether or not an accessible drag operation is in progress. */
-    private boolean mIsAccessibleDrag;
+    /** Options controlling the drag behavior. */
+    private DragOptions mOptions;
 
     /** X coordinate of the down event. */
     private int mMotionDownX;
@@ -145,12 +139,10 @@
         /**
          * A drag has begun
          *
-         * @param source An object representing where the drag originated
-         * @param info The data associated with the object that is being dragged
-         * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
-         *        or {@link DragController#DRAG_ACTION_COPY}
+         * @param dragObject The object being dragged
+         * @param options Options used to start the drag
          */
-        void onDragStart(DragSource source, ItemInfo info, int dragAction);
+        void onDragStart(DropTarget.DragObject dragObject, DragOptions options);
 
         /**
          * The drag has ended
@@ -160,8 +152,6 @@
 
     /**
      * Used to create a new DragLayer from XML.
-     *
-     * @param context The application's context.
      */
     public DragController(Launcher launcher) {
         Resources r = launcher.getResources();
@@ -183,11 +173,9 @@
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
      * @param viewImageBounds the position of the image inside the view
-     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
-     *        {@link #DRAG_ACTION_COPY}
      */
     public void startDrag(View v, Bitmap bmp, DragSource source, ItemInfo dragInfo,
-            Rect viewImageBounds, int dragAction, float initialDragViewScale) {
+            Rect viewImageBounds, float initialDragViewScale, DragOptions options) {
         int[] loc = mCoordinatesTemp;
         mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
         int dragLayerX = loc[0] + viewImageBounds.left
@@ -195,12 +183,8 @@
         int dragLayerY = loc[1] + viewImageBounds.top
                 + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
 
-        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
-                null, initialDragViewScale, false);
-
-        if (dragAction == DRAG_ACTION_MOVE) {
-            v.setVisibility(View.GONE);
-        }
+        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, null,
+                null, initialDragViewScale, options);
     }
 
     /**
@@ -212,15 +196,12 @@
      * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
-     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
-     *        {@link #DRAG_ACTION_COPY}
      * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
      *          Makes dragging feel more precise, e.g. you can clip out a transparent border
-     * @param accessible whether this drag should occur in accessibility mode
      */
     public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
-            DragSource source, ItemInfo dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
-            float initialDragViewScale, boolean accessible) {
+            DragSource source, ItemInfo dragInfo, Point dragOffset, Rect dragRegion,
+            float initialDragViewScale, DragOptions options) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
         }
@@ -232,19 +213,15 @@
         }
         mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
 
-        for (DragListener listener : mListeners) {
-            listener.onDragStart(source, dragInfo, dragAction);
-        }
-
         final int registrationX = mMotionDownX - dragLayerX;
         final int registrationY = mMotionDownY - dragLayerY;
 
         final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
         final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
 
-        mIsAccessibleDrag = accessible;
         mLastDropTarget = null;
 
+        mOptions = options;
         mDragObject = new DropTarget.DragObject();
 
         final Resources res = mLauncher.getResources();
@@ -254,7 +231,7 @@
                 registrationY, initialDragViewScale, scaleDps);
 
         mDragObject.dragComplete = false;
-        if (mIsAccessibleDrag) {
+        if (mOptions.isAccessibleDrag) {
             // For an accessible drag, we assume the view is being dragged from the center.
             mDragObject.xOffset = b.getWidth() / 2;
             mDragObject.yOffset = b.getHeight() / 2;
@@ -282,6 +259,11 @@
         mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
         dragView.show(mMotionDownX, mMotionDownY);
         mDistanceSinceScroll = 0;
+
+        for (DragListener listener : new ArrayList<>(mListeners)) {
+            listener.onDragStart(mDragObject, mOptions);
+        }
+
         mLastTouch[0] = mMotionDownX;
         mLastTouch[1] = mMotionDownY;
         handleMoveEvent(mMotionDownX, mMotionDownY);
@@ -308,7 +290,7 @@
     }
 
     public boolean isDragging() {
-        return mDragDriver != null || mIsAccessibleDrag;
+        return mDragDriver != null || (mOptions != null && mOptions.isAccessibleDrag);
     }
 
     /**
@@ -343,7 +325,7 @@
     private void endDrag() {
         if (isDragging()) {
             mDragDriver = null;
-            mIsAccessibleDrag = false;
+            mOptions = null;
             clearScrollRunnable();
             boolean isDeferred = false;
             if (mDragObject.dragView != null) {
@@ -422,10 +404,6 @@
 
     @Override
     public void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride) {
-        final int[] dragLayerPos = getClampedDragLayerPos(x, y);
-        final int dragLayerX = dragLayerPos[0];
-        final int dragLayerY = dragLayerPos[1];
-
         DropTarget dropTarget;
         PointF vec = null;
 
@@ -454,14 +432,7 @@
      * Call this from a drag source view.
      */
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        @SuppressWarnings("all") // suppress dead code warning
-        final boolean debug = false;
-        if (debug) {
-            Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " Dragging="
-                    + (mDragDriver != null));
-        }
-
-        if (mIsAccessibleDrag) {
+        if (mOptions != null && mOptions.isAccessibleDrag) {
             return false;
         }
 
@@ -604,7 +575,7 @@
      * Call this from a drag source view.
      */
     public boolean onTouchEvent(MotionEvent ev) {
-        if (mDragDriver == null || mIsAccessibleDrag) {
+        if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
             return false;
         }
 
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index dcff89f..5863828 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -343,16 +343,9 @@
     }
 
     private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
-        AccessibilityManager accessibilityManager = (AccessibilityManager)
-                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-        if (accessibilityManager.isEnabled()) {
-            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
-            AccessibilityEvent event = AccessibilityEvent.obtain(
-                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
-            onInitializeAccessibilityEvent(event);
-            event.getText().add(getContext().getString(stringId));
-            accessibilityManager.sendAccessibilityEvent(event);
-        }
+        int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
+        Utilities.sendCustomAccessibilityEvent(
+                this, AccessibilityEvent.TYPE_VIEW_FOCUSED, getContext().getString(stringId));
     }
 
     private boolean isInAccessibleDrag() {
@@ -362,37 +355,27 @@
     @Override
     public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
         // Shortcuts can appear above folder
-        View topView = mLauncher.getOpenShortcutsContainer();
+        View topView = mLauncher.getTopFloatingView();
         if (topView != null) {
-            return handleTopViewSendAccessibilityEvent(topView, child, event);
-        }
-
-        topView = mLauncher.getWorkspace().getOpenFolder();
-        if (topView != null) {
-            return handleTopViewSendAccessibilityEvent(topView, child, event);
+            if (child == topView) {
+                return super.onRequestSendAccessibilityEvent(child, event);
+            }
+            if (isInAccessibleDrag() && child instanceof DropTargetBar) {
+                return super.onRequestSendAccessibilityEvent(child, event);
+            }
+            // Skip propagating onRequestSendAccessibilityEvent for all other children
+            // which are not topView
+            return false;
         }
         return super.onRequestSendAccessibilityEvent(child, event);
     }
 
-    private boolean handleTopViewSendAccessibilityEvent(
-            View topView, View child, AccessibilityEvent event) {
-        if (child == topView) {
-            return super.onRequestSendAccessibilityEvent(child, event);
-        }
-        if (isInAccessibleDrag() && child instanceof DropTargetBar) {
-            return super.onRequestSendAccessibilityEvent(child, event);
-        }
-        // Skip propagating onRequestSendAccessibilityEvent for all other children
-        // which are not topView
-        return false;
-    }
-
     @Override
     public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
-        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
-        if (currentFolder != null) {
-            // Only add the folder as a child for accessibility when it is open
-            childrenForAccessibility.add(currentFolder);
+        View topView = mLauncher.getTopFloatingView();
+        if (topView != null) {
+            // Only add the top view as a child for accessibility when it is open
+            childrenForAccessibility.add(topView);
 
             if (isInAccessibleDrag()) {
                 childrenForAccessibility.add(mLauncher.getDropTargetBar());
@@ -523,7 +506,9 @@
 
     @Override
     public boolean dispatchUnhandledMove(View focused, int direction) {
-        return mDragController.dispatchUnhandledMove(focused, direction);
+        // Consume the unhandled move if a container is open, to avoid switching pages underneath.
+        boolean isContainerOpen = mLauncher.getTopFloatingView() != null;
+        return isContainerOpen || mDragController.dispatchUnhandledMove(focused, direction);
     }
 
     @Override
@@ -1037,6 +1022,26 @@
         return mBackgroundAlpha;
     }
 
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        View topView = mLauncher.getTopFloatingView();
+        if (topView != null) {
+            return topView.requestFocus(direction, previouslyFocusedRect);
+        } else {
+            return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
+        }
+    }
+
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        View topView = mLauncher.getTopFloatingView();
+        if (topView != null) {
+            topView.addFocusables(views, direction);
+        } else {
+            super.addFocusables(views, direction, focusableMode);
+        }
+    }
+
     public void setTouchCompleteListener(TouchCompleteListener listener) {
         mTouchCompleteListener = listener;
     }
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
new file mode 100644
index 0000000..a7f2872
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.dragndrop;
+
+/**
+ * Set of options to control the drag and drop behavior.
+ */
+public class DragOptions {
+
+    /** Whether or not an accessible drag operation is in progress. */
+    public boolean isAccessibleDrag = false;
+}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 5450423..19956a9 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -42,7 +42,6 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.EditorInfo;
@@ -52,7 +51,6 @@
 
 import com.android.launcher3.Alarm;
 import com.android.launcher3.CellLayout;
-import com.android.launcher3.CellLayout.CellInfo;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget;
@@ -71,12 +69,12 @@
 import com.android.launcher3.UninstallDropTarget.DropTargetSource;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace.ItemOperator;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.accessibility.AccessibileDragListenerAdapter;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragController.DragListener;
 import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.logging.UserEventDispatcher.LaunchSourceProvider;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -92,7 +90,7 @@
  */
 public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
         View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
-        View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource {
+        View.OnFocusChangeListener, DragListener, DropTargetSource {
     private static final String TAG = "Launcher.Folder";
 
     /**
@@ -282,10 +280,10 @@
     public boolean onLongClick(View v) {
         // Return if global dragging is not enabled
         if (!mLauncher.isDraggingEnabled()) return true;
-        return beginDrag(v, false);
+        return startDrag(v, new DragOptions());
     }
 
-    private boolean beginDrag(View v, boolean accessible) {
+    public boolean startDrag(View v, DragOptions options) {
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
             ShortcutInfo item = (ShortcutInfo) tag;
@@ -293,35 +291,48 @@
                 return false;
             }
 
-            mLauncher.getWorkspace().beginDragShared(v, this, accessible);
-
             mCurrentDragInfo = item;
             mEmptyCellRank = item.rank;
             mCurrentDragView = v;
 
-            mContent.removeItem(mCurrentDragView);
-            mInfo.remove(mCurrentDragInfo, true);
-            mDragInProgress = true;
-            mItemAddedBackToSelfViaIcon = false;
+            mDragController.addDragListener(this);
+            if (options.isAccessibleDrag) {
+                mDragController.addDragListener(new AccessibileDragListenerAdapter(
+                        mContent, CellLayout.FOLDER_ACCESSIBILITY_DRAG) {
+
+                    @Override
+                    protected void enableAccessibleDrag(boolean enable) {
+                        super.enableAccessibleDrag(enable);
+                        mFooter.setImportantForAccessibility(enable
+                                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                                : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+                    }
+                });
+            }
+
+            mLauncher.getWorkspace().beginDragShared(v, this, options);
         }
         return true;
     }
 
     @Override
-    public void startDrag(CellInfo cellInfo, boolean accessible) {
-        beginDrag(cellInfo.cell, accessible);
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+        if (dragObject.dragSource != this) {
+            return;
+        }
+
+        mContent.removeItem(mCurrentDragView);
+        mInfo.remove(mCurrentDragInfo, true);
+        mDragInProgress = true;
+        mItemAddedBackToSelfViaIcon = false;
     }
 
     @Override
-    public void enableAccessibleDrag(boolean enable) {
-        mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
-        for (int i = 0; i < mContent.getChildCount(); i++) {
-            mContent.getPageAt(i).enableAccessibleDrag(enable, CellLayout.FOLDER_ACCESSIBILITY_DRAG);
+    public void onDragEnd() {
+        if (mIsExternalDrag && mDragInProgress) {
+            completeDragExit();
         }
-
-        mFooter.setImportantForAccessibility(enable ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS :
-                IMPORTANT_FOR_ACCESSIBILITY_AUTO);
-        mLauncher.getWorkspace().setAddNewPageOnDrag(!enable);
+        mDragController.removeDragListener(this);
     }
 
     public boolean isEditingName() {
@@ -352,7 +363,8 @@
         LauncherModel.updateItemInDatabase(mLauncher, mInfo);
 
         if (commit) {
-            sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+            Utilities.sendCustomAccessibilityEvent(
+                    this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
                     getContext().getString(R.string.folder_renamed, newTitle));
         }
 
@@ -591,7 +603,9 @@
         openFolderAnim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                Utilities.sendCustomAccessibilityEvent(
+                        Folder.this,
+                        AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
                         mContent.getAccessibilityDescription());
                 mState = STATE_ANIMATING;
             }
@@ -661,28 +675,6 @@
         mDragController.addDragListener(this);
     }
 
-    @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
-
-    @Override
-    public void onDragEnd() {
-        if (mIsExternalDrag && mDragInProgress) {
-            completeDragExit();
-        }
-        mDragController.removeDragListener(this);
-    }
-
-    @Thunk void sendCustomAccessibilityEvent(int type, String text) {
-        AccessibilityManager accessibilityManager = (AccessibilityManager)
-                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-        if (accessibilityManager.isEnabled()) {
-            AccessibilityEvent event = AccessibilityEvent.obtain(type);
-            onInitializeAccessibilityEvent(event);
-            event.getText().add(text);
-            accessibilityManager.sendAccessibilityEvent(event);
-        }
-    }
-
     public void animateClosed() {
         if (!(getParent() instanceof DragLayer)) return;
         final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 0, 0.9f, 0.9f);
@@ -694,7 +686,9 @@
             }
             @Override
             public void onAnimationStart(Animator animation) {
-                sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                Utilities.sendCustomAccessibilityEvent(
+                        Folder.this,
+                        AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
                         getContext().getString(R.string.folder_closed));
                 mState = STATE_ANIMATING;
             }
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index e078d9b..bc91c15 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -27,7 +27,6 @@
 import com.android.launcher3.HolographicOutlineHelper;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.PreloadIconDrawable;
-import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.folder.FolderIcon;
@@ -134,14 +133,12 @@
      * Responsibility for the bitmap is transferred to the caller.
      */
     public Bitmap createDragOutline(Canvas canvas) {
-        final int outlineColor = mView.getResources().getColor(R.color.outline_color);
         final Bitmap b = Bitmap.createBitmap(mView.getWidth() + DRAG_BITMAP_PADDING,
-                mView.getHeight() + DRAG_BITMAP_PADDING, Bitmap.Config.ARGB_8888);
-
+                mView.getHeight() + DRAG_BITMAP_PADDING, Bitmap.Config.ALPHA_8);
         canvas.setBitmap(b);
         drawDragView(canvas);
         HolographicOutlineHelper.obtain(mView.getContext())
-                .applyExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
+                .applyExpensiveOutlineWithBlur(b, canvas);
         canvas.setBitmap(null);
         return b;
     }
diff --git a/src/com/android/launcher3/pageindicators/CaretDrawable.java b/src/com/android/launcher3/pageindicators/CaretDrawable.java
index 1451773..4789f69 100644
--- a/src/com/android/launcher3/pageindicators/CaretDrawable.java
+++ b/src/com/android/launcher3/pageindicators/CaretDrawable.java
@@ -37,6 +37,7 @@
     private Paint mShadowPaint = new Paint();
     private Paint mCaretPaint = new Paint();
     private Path mPath = new Path();
+    private final int mCaretSizePx;
 
     public CaretDrawable(Context context) {
         final Resources res = context.getResources();
@@ -57,6 +58,18 @@
         mShadowPaint.setStyle(Paint.Style.STROKE);
         mShadowPaint.setStrokeCap(Paint.Cap.ROUND);
         mShadowPaint.setStrokeJoin(Paint.Join.ROUND);
+
+        mCaretSizePx = res.getDimensionPixelSize(R.dimen.all_apps_caret_size);
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mCaretSizePx;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mCaretSizePx;
     }
 
     @Override
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index b53715d..47c2ffb 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -18,20 +18,21 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.view.View;
+import android.widget.FrameLayout;
 
 import com.android.launcher3.dynamicui.ExtractedColors;
 
 /**
  * Base class for a page indicator.
  */
-public abstract class PageIndicator extends View {
+public abstract class PageIndicator extends FrameLayout {
     private CaretDrawable mCaretDrawable;
 
     protected int mNumPages = 1;
 
     public PageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        setWillNotDraw(false);
     }
 
     public void setScroll(int currentScroll, int totalScroll) {}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
index 0d771ad..ca3a2dd 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
@@ -15,14 +15,13 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Property;
-import android.view.View;
 import android.view.ViewConfiguration;
+import android.widget.ImageView;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.dynamicui.ExtractedColors;
-import com.android.launcher3.util.TransformingTouchDelegate;
 
 /**
  * A PageIndicator that briefly shows a fraction of a line when moving between pages.
@@ -60,10 +59,7 @@
     private Paint mLinePaint;
     private Launcher mLauncher;
     private final int mLineHeight;
-    private final TransformingTouchDelegate mTouchDelegate;
-    private final int mTouchExtensionHeight;
-    private final int mCaretSizePx;
-    private final int mCaretWorkspaceOffsetPx;
+    private ImageView mAllAppsHandle;
 
     private static final Property<PageIndicatorLineCaret, Integer> PAINT_ALPHA
             = new Property<PageIndicatorLineCaret, Integer>(Integer.class, "paint_alpha") {
@@ -128,48 +124,26 @@
         Resources res = context.getResources();
         mLinePaint = new Paint();
         mLinePaint.setAlpha(0);
-        mCaretSizePx = res.getDimensionPixelSize(R.dimen.all_apps_caret_size);
-        mCaretWorkspaceOffsetPx = res.getDimensionPixelSize(
-                R.dimen.all_apps_caret_workspace_offset);
 
         mLauncher = (Launcher) context;
-        setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
-        setOnClickListener(mLauncher);
-        setOnLongClickListener(mLauncher);
-        setOnFocusChangeListener(mLauncher.mFocusHandler);
-        setCaretDrawable(new CaretDrawable(context));
         mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
-        mTouchExtensionHeight = res.getDimensionPixelSize(
-                R.dimen.dynamic_grid_page_indicator_extra_touch_height);
-        mTouchDelegate = new TransformingTouchDelegate(this);
+        setCaretDrawable(new CaretDrawable(context));
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mLauncher.getDragLayer().setTouchDelegate(mTouchDelegate);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        // Top/center align the caret in the page indicator space
-        int l = (right - left) / 2 - mCaretSizePx / 2;
-        getCaretDrawable().setBounds(l, mCaretWorkspaceOffsetPx, l + mCaretSizePx,
-                mCaretWorkspaceOffsetPx + mCaretSizePx);
-
-        // The touch area is expanded below this view by #mTouchExtensionHeight
-        // which extends to the top of the hotseat.
-        View parent = mLauncher.getDragLayer();
-        sTempCoords[0] = sTempCoords[1] = 0;
-        Utilities.getDescendantCoordRelativeToAncestor(this, parent, sTempCoords, true);
-        mTouchDelegate.setBounds(sTempCoords[0], sTempCoords[1], sTempCoords[0] + this.getWidth(),
-                sTempCoords[1] + getHeight() + mTouchExtensionHeight);
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mAllAppsHandle = (ImageView) findViewById(R.id.all_apps_handle);
+        mAllAppsHandle.setImageDrawable(getCaretDrawable());
+        mAllAppsHandle.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+        mAllAppsHandle.setOnClickListener(mLauncher);
+        mAllAppsHandle.setOnLongClickListener(mLauncher);
+        mAllAppsHandle.setOnFocusChangeListener(mLauncher.mFocusHandler);
+        mLauncher.setAllAppsButton(mAllAppsHandle);
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
-        getCaretDrawable().draw(canvas);
         if (mTotalScroll == 0 || mNumPagesFloat == 0) {
             return;
         }
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 0ff13a7..cfa6efd 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -31,7 +31,6 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
@@ -62,9 +61,9 @@
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.graphics.TriangleShape;
-import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 
@@ -254,8 +253,10 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mOpenCloseAnimator = null;
-
-                sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+                Utilities.sendCustomAccessibilityEvent(
+                        DeepShortcutsContainer.this,
+                        AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                        getContext().getString(R.string.action_deep_shortcut));
             }
         });
 
@@ -515,8 +516,8 @@
         mIconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx;
 
         DragView dv = mLauncher.getWorkspace().beginDragShared(
-                sv.getBubbleText(), this, false, sv.getFinalInfo(),
-                new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift));
+                sv.getBubbleText(), this, sv.getFinalInfo(),
+                new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift), new DragOptions());
         dv.animateShift(-mIconShift.x, -mIconShift.y);
 
         // TODO: support dragging from within folder without having to close it
@@ -560,7 +561,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
         // Either the original icon or one of the shortcuts was dragged.
         // Hide the container, but don't remove it yet because that interferes with touch events.
         animateClose();
@@ -577,8 +578,7 @@
             } else {
                 // Close animation is not running.
                 if (mDeferContainerRemoval) {
-                    mDeferContainerRemoval = false;
-                    mLauncher.getDragLayer().removeView(this);
+                    close();
                 }
             }
         }
@@ -599,7 +599,6 @@
             mOpenCloseAnimator.cancel();
         }
         mIsOpen = false;
-        mLauncher.getDragController().removeDragListener(this);
 
         final AnimatorSet shortcutAnims = LauncherAnimUtils.createAnimatorSet();
         final int shortcutCount = getShortcutCount();
diff --git a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
index a25e475..2adb82e 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
@@ -22,12 +22,9 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.view.View;
-import android.widget.ImageView;
 
-import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.HolographicOutlineHelper;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.graphics.DragPreviewProvider;
 
@@ -45,23 +42,22 @@
 
     @Override
     public Bitmap createDragOutline(Canvas canvas) {
-        Bitmap b = drawScaledPreview(canvas);
+        Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ALPHA_8);
 
-        final int outlineColor = mView.getResources().getColor(R.color.outline_color);
         HolographicOutlineHelper.obtain(mView.getContext())
-                .applyExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
+                .applyExpensiveOutlineWithBlur(b, canvas);
         canvas.setBitmap(null);
         return b;
     }
 
     @Override
     public Bitmap createDragBitmap(Canvas canvas) {
-        Bitmap b = drawScaledPreview(canvas);
+        Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ARGB_8888);
         canvas.setBitmap(null);
         return b;
     }
 
-    private Bitmap drawScaledPreview(Canvas canvas) {
+    private Bitmap drawScaledPreview(Canvas canvas, Bitmap.Config config) {
         Drawable d = mView.getBackground();
         Rect bounds = getDrawableBounds(d);
 
@@ -70,7 +66,7 @@
         final Bitmap b = Bitmap.createBitmap(
                 size + DRAG_BITMAP_PADDING,
                 size + DRAG_BITMAP_PADDING,
-                Bitmap.Config.ARGB_8888);
+                config);
 
         canvas.setBitmap(b);
         canvas.save(Canvas.MATRIX_SAVE_FLAG);
diff --git a/src/com/android/launcher3/util/ActivityResultInfo.java b/src/com/android/launcher3/util/ActivityResultInfo.java
new file mode 100644
index 0000000..2261bee
--- /dev/null
+++ b/src/com/android/launcher3/util/ActivityResultInfo.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Utility class which stores information from onActivityResult
+ */
+public class ActivityResultInfo implements Parcelable {
+
+    public final int requestCode;
+    public final int resultCode;
+    public final Intent data;
+
+    public ActivityResultInfo(int requestCode, int resultCode, Intent data) {
+        this.requestCode = requestCode;
+        this.resultCode = resultCode;
+        this.data = data;
+    }
+
+    private ActivityResultInfo(Parcel parcel) {
+        requestCode = parcel.readInt();
+        resultCode = parcel.readInt();
+        data = parcel.readInt() != 0 ? Intent.CREATOR.createFromParcel(parcel) : null;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(requestCode);
+        dest.writeInt(resultCode);
+        if (data != null) {
+            dest.writeInt(1);
+            data.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
+    public static final Parcelable.Creator<ActivityResultInfo> CREATOR =
+            new Parcelable.Creator<ActivityResultInfo>() {
+                public ActivityResultInfo createFromParcel(Parcel source) {
+                    return new ActivityResultInfo(source);
+                }
+
+                public ActivityResultInfo[] newArray(int size) {
+                    return new ActivityResultInfo[size];
+                }
+            };
+}
diff --git a/src/com/android/launcher3/util/PendingRequestArgs.java b/src/com/android/launcher3/util/PendingRequestArgs.java
new file mode 100644
index 0000000..4e402f3
--- /dev/null
+++ b/src/com/android/launcher3/util/PendingRequestArgs.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.content.ContentValues;
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+
+/**
+ * Utility class to store information regarding a pending request made by launcher. This information
+ * can be saved across launcher instances.
+ */
+public class PendingRequestArgs extends ItemInfo implements Parcelable {
+
+    private static final int TYPE_NONE = 0;
+    private static final int TYPE_INTENT = 1;
+    private static final int TYPE_APP_WIDGET = 2;
+
+    private final int mArg1;
+    private final int mObjectType;
+    private final Parcelable mObject;
+
+    public PendingRequestArgs(ItemInfo info) {
+        mArg1 = 0;
+        mObjectType = TYPE_NONE;
+        mObject = null;
+
+        copyFrom(info);
+    }
+
+    private PendingRequestArgs(int arg1, int objectType, Parcelable object) {
+        mArg1 = arg1;
+        mObjectType = objectType;
+        mObject = object;
+    }
+
+    public PendingRequestArgs(Parcel parcel) {
+        readFromValues(ContentValues.CREATOR.createFromParcel(parcel));
+
+        mArg1 = parcel.readInt();
+        mObjectType = parcel.readInt();
+        if (parcel.readInt() != 0) {
+            mObject = mObjectType == TYPE_INTENT
+                    ? Intent.CREATOR.createFromParcel(parcel)
+                    : new LauncherAppWidgetProviderInfo(parcel);
+        } else {
+            mObject = null;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        ContentValues itemValues = new ContentValues();
+        writeToValues(itemValues);
+
+        dest.writeInt(mArg1);
+        dest.writeInt(mObjectType);
+        if (mObject != null) {
+            dest.writeInt(1);
+            mObject.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
+    public LauncherAppWidgetProviderInfo getWidgetProvider() {
+        return mObjectType == TYPE_APP_WIDGET ? (LauncherAppWidgetProviderInfo) mObject : null;
+    }
+
+    public int getWidgetId() {
+        return mObjectType == TYPE_APP_WIDGET ? mArg1 : 0;
+    }
+
+    public Intent getPendingIntent() {
+        return mObjectType == TYPE_INTENT ? (Intent) mObject : null;
+    }
+
+    public int getRequestCode() {
+        return mObjectType == TYPE_INTENT ? mArg1 : 0;
+    }
+
+    public static PendingRequestArgs forWidgetInfo(
+            int appWidgetId, LauncherAppWidgetProviderInfo widgetInfo, ItemInfo info) {
+        PendingRequestArgs args = new PendingRequestArgs(appWidgetId, TYPE_APP_WIDGET, widgetInfo);
+        args.copyFrom(info);
+        return args;
+    }
+
+    public static PendingRequestArgs forIntent(int requestCode, Intent intent, ItemInfo info) {
+        PendingRequestArgs args = new PendingRequestArgs(requestCode, TYPE_INTENT, intent);
+        args.copyFrom(info);
+        return args;
+    }
+
+    public static final Parcelable.Creator<PendingRequestArgs> CREATOR =
+            new Parcelable.Creator<PendingRequestArgs>() {
+                public PendingRequestArgs createFromParcel(Parcel source) {
+                    return new PendingRequestArgs(source);
+                }
+
+                public PendingRequestArgs[] newArray(int size) {
+                    return new PendingRequestArgs[size];
+                }
+            };
+}
diff --git a/src/com/android/launcher3/widget/PendingItemPreviewProvider.java b/src/com/android/launcher3/widget/PendingItemPreviewProvider.java
index 8739390..eaa0bb3 100644
--- a/src/com/android/launcher3/widget/PendingItemPreviewProvider.java
+++ b/src/com/android/launcher3/widget/PendingItemPreviewProvider.java
@@ -24,7 +24,6 @@
 import com.android.launcher3.HolographicOutlineHelper;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.graphics.DragPreviewProvider;
 
@@ -50,7 +49,7 @@
 
         int w = size[0];
         int h = size[1];
-        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8);
         canvas.setBitmap(b);
 
         Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
@@ -68,9 +67,8 @@
         // Don't clip alpha values for the drag outline if we're using the default widget preview
         boolean clipAlpha = !(mAddInfo instanceof PendingAddWidgetInfo &&
                 (((PendingAddWidgetInfo) mAddInfo).previewImage == 0));
-        final int outlineColor = mView.getResources().getColor(R.color.outline_color);
         HolographicOutlineHelper.obtain(mView.getContext())
-                .applyExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor, clipAlpha);
+                .applyExpensiveOutlineWithBlur(b, canvas, clipAlpha);
         canvas.setBitmap(null);
 
         return b;
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 297505b..049871f 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -11,6 +11,7 @@
 
 import com.android.launcher3.AppWidgetResizeFrame;
 import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
@@ -18,6 +19,7 @@
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.util.Thunk;
 
 public class WidgetHostViewLoader implements DragController.DragListener {
@@ -47,7 +49,7 @@
     }
 
     @Override
-    public void onDragStart(DragSource source, ItemInfo info, int dragAction) { }
+    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { }
 
     @Override
     public void onDragEnd() {
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 4b2be18..70b2945 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.DeleteDropTarget;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.IconCache;
 import com.android.launcher3.ItemInfo;
@@ -251,7 +252,7 @@
 
         // Start the drag
         mDragController.startDrag(image, preview, this, createItemInfo,
-                bounds, DragController.DRAG_ACTION_COPY, scale);
+                bounds, scale, new DragOptions());
         return true;
     }