Merge "Do not apply legacy treatment on shortcuts Bug: 62617041" into ub-launcher3-dorval-polish
diff --git a/res/color-v24/all_apps_bg_hand_fill_dark.xml b/res/color-v24/all_apps_bg_hand_fill_dark.xml
new file mode 100644
index 0000000..bb9c71c
--- /dev/null
+++ b/res/color-v24/all_apps_bg_hand_fill_dark.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<gradient
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:startX="158.5"
+    android:startY="141.5"
+    android:endX="196.0"
+    android:endY="206.5"
+    android:type="linear" >
+    <item android:offset="0" android:color="#9AA0A6" />
+    <item android:offset="0.1013" android:color="#E5A5ABB0" />
+    <item android:offset="0.4946" android:color="#81CDCFD1" />
+    <item android:offset="0.8079" android:color="#31E5E6E6" />
+    <item android:offset="1" android:color="#00EEEEEE" />
+</gradient>
\ No newline at end of file
diff --git a/res/drawable/ic_all_apps_bg_hand.xml b/res/drawable/ic_all_apps_bg_hand.xml
index 94af008..7f3fe14 100644
--- a/res/drawable/ic_all_apps_bg_hand.xml
+++ b/res/drawable/ic_all_apps_bg_hand.xml
@@ -42,7 +42,7 @@
                 c0.3,1.7,1.9,2.9,3.6,2.7l40-6.1c1.7-0.3,2.9-1.9,2.7-3.6L54.4,21L41.7,23z M37.5,23.6l-12.6,1.9l-0.3-2.1l12.6-1.9L37.5,23.6z"/>
     </group>
     <path
-        android:fillColor="#BDBDBD"
+        android:fillColor="?android:attr/colorControlHighlight"
         android:pathData="M87.5,62.9h-4.4l-1.6-1.5c5.5-6.4,8.8-14.7,8.8-23.7C90.3,17.7,74,1.4,54,1.4
         S17.6,17.7,17.6,37.7S33.9,74.1,54,74.1c9,0,17.3-3.3,23.7-8.8l1.5,1.6v4.4l40.5,40.4l8.3-8.3L87.5,62.9z M54,64.2
         c-14.7,0-26.5-11.8-26.5-26.5S39.3,11.2,54,11.2s26.5,11.8,26.5,26.5S68.6,64.2,54,64.2z"/>
@@ -92,7 +92,7 @@
         c-0.7-0.1-1.3-0.2-2,0.2c-1,0.6-1.2,1.5-1.3,2.4c-0.2,1.8,0.6,3.9,1.6,5.9L107,87.3l0.2,0.4l6.6,11.7l0,0
         c2.5,4.5,4.4,10.5,4.4,10.7L129.7,125.1"/>
     <path
-        android:fillColor="@color/all_apps_bg_hand_fill"
+        android:fillColor="?android:attr/colorForeground"
         android:pathData="M202.3,183.1c-5.4-14.1-23.8-44.3-26.7-49c-0.2-0.3-0.6-0.3-0.8,0
         c-5.1,6.6-19,11.4-26.5,13.6c-0.3,0.1-1,0.1-1.2,0.6c-0.2,0.4,0.1,1,0.2,1.1c7.8,12.9,14.7,27.9,15.3,29.3c0,0.1,0.1,0.1,0.1,0.2
         l9.6,22.9c0,0,0,0,0,0l1.7,4.1c1.4,2.7,3,4.3,5.3,5.1c1.5,0.5,2.1,0.6,3.2,0.6c4.8,0.1,15.2-6.1,20.5-9.4c2.7-1.7,3.3-4.4,2.9-7.6
diff --git a/res/drawable/ic_all_apps_bg_icon_1.xml b/res/drawable/ic_all_apps_bg_icon_1.xml
index c9c0a75..d226ac6 100644
--- a/res/drawable/ic_all_apps_bg_icon_1.xml
+++ b/res/drawable/ic_all_apps_bg_icon_1.xml
@@ -25,7 +25,7 @@
         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:fillColor="?android:attr/colorPrimary"
         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
index b6269e3..5966d99 100644
--- a/res/drawable/ic_all_apps_bg_icon_2.xml
+++ b/res/drawable/ic_all_apps_bg_icon_2.xml
@@ -26,7 +26,7 @@
         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:fillColor="?android:attr/colorPrimary"
         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" />
diff --git a/res/drawable/ic_all_apps_bg_icon_3.xml b/res/drawable/ic_all_apps_bg_icon_3.xml
index 4c255a9..b18f8bc 100644
--- a/res/drawable/ic_all_apps_bg_icon_3.xml
+++ b/res/drawable/ic_all_apps_bg_icon_3.xml
@@ -26,11 +26,11 @@
         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:fillColor="?android:attr/colorPrimary"
         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:fillColor="?android:attr/colorPrimary"
         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
index 12e05bc..8eb4d90 100644
--- a/res/drawable/ic_all_apps_bg_icon_4.xml
+++ b/res/drawable/ic_all_apps_bg_icon_4.xml
@@ -25,7 +25,7 @@
         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:fillColor="?android:attr/colorPrimary"
         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
diff --git a/res/drawable/ic_remove_no_shadow.xml b/res/drawable/ic_remove_no_shadow.xml
index ef538a6..be7f9f3 100644
--- a/res/drawable/ic_remove_no_shadow.xml
+++ b/res/drawable/ic_remove_no_shadow.xml
@@ -21,5 +21,7 @@
         android:tint="?android:attr/textColorPrimary" >
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
+        android:pathData="M13.41,12l5.29-5.29c0.39-0.39,0.39-1.02,0-1.41c-0.39-0.39-1.02-0.39-1.41,0L12,10.59L6.71,
+        5.29c-0.39-0.39-1.02-0.39-1.41,0c-0.39,0.39-0.39,1.02,0,1.41L10.59,12l-5.29,5.29c-0.39,0.39-0.39,1.02,
+        0,1.41c0.39,0.39,1.02,0.39,1.41,0L12,13.41l5.29,5.29c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,0.39-1.02,0-1.41L13.41,12z"/>
 </vector>
diff --git a/res/drawable/ic_setting.xml b/res/drawable/ic_setting.xml
index b0009c5..1bab189 100644
--- a/res/drawable/ic_setting.xml
+++ b/res/drawable/ic_setting.xml
@@ -20,5 +20,11 @@
         android:viewportHeight="48.0">
     <path
         android:fillColor="?android:attr/textColorPrimary"
-        android:pathData="M38.86 25.95c.08-.64 .14-1.29 .14-1.95s-.06-1.31-.14-1.95l4.23-3.31c.38-.3 .49-.84 .24-1.28l-4-6.93c-.25-.43-.77-.61-1.22-.43l-4.98 2.01c-1.03-.79-2.16-1.46-3.38-1.97L29 4.84c-.09-.47-.5-.84-1-.84h-8c-.5 0-.91 .37-.99 .84l-.75 5.3c-1.22 .51-2.35 1.17-3.38 1.97L9.9 10.1c-.45-.17-.97 0-1.22 .43l-4 6.93c-.25 .43-.14 .97 .24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31 .14 1.95l-4.22 3.31c-.38 .3-.49 .84-.24 1.28l4 6.93c.25 .43 .77 .61 1.22 .43l4.98-2.01c1.03 .79 2.16 1.46 3.38 1.97l.75 5.3c.08 .47 .49 .84 .99 .84h8c.5 0 .91-.37 .99-.84l.75-5.3c1.22-.51 2.35-1.17 3.38-1.97l4.98 2.01c.45 .17 .97 0 1.22-.43l4-6.93c.25-.43 .14-.97-.24-1.28l-4.22-3.31zM24 31c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/>
+        android:pathData="M42.8,28.4l-3.88-2.9c0.06-0.5,0.08-1,0.08-1.52s-0.02-1.02-0.08-1.52l3.88-2.86c0.84-0.62,1.04-1.88,
+        0.48-2.82l-3.2-5.52c-0.56-0.96-1.76-1.4-2.72-1l-4.28,1.82c-0.96-0.74-2.02-1.36-3.14-1.84l-0.54-4.4C29.28,4.8,28.28,4,
+        27.18,4h-6.36c-1.1,0-2.1,0.8-2.22,1.84l-0.52,4.38c-1.14,0.48-2.2,1.1-3.16,1.84l-4.28-1.82c-0.96-0.4-2.16,0.04-2.72,
+        1l-3.2,5.52c-0.56,0.96-0.36,2.2,0.48,2.84l3.88,2.9C9.02,22.98,9,23.48,9,24s0.02,1.02,0.08,1.52L5.2,28.4c-0.84,0.62-1.04,
+        1.88-0.48,2.82l3.2,5.52c0.56,0.96,1.76,1.4,2.72,1l4.28-1.82c0.96,0.74,2.02,1.36,3.14,1.84l0.54,4.38C18.72,43.2,19.72,
+        44,20.82,44h6.36c1.1,0,2.08-0.8,2.22-1.84l0.54-4.38c1.12-0.48,2.18-1.1,3.14-1.84l4.28,1.82c0.96,0.4,2.16-0.04,
+        2.72-1l3.2-5.52C43.84,30.28,43.64,29.04,42.8,28.4z M24,31c-3.86,0-7-3.14-7-7s3.14-7,7-7s7,3.14,7,7S27.86,31,24,31z"/>
 </vector>
diff --git a/res/drawable/ic_uninstall_no_shadow.xml b/res/drawable/ic_uninstall_no_shadow.xml
index 5bab422..2a86e10 100644
--- a/res/drawable/ic_uninstall_no_shadow.xml
+++ b/res/drawable/ic_uninstall_no_shadow.xml
@@ -21,5 +21,6 @@
         android:tint="?android:attr/textColorPrimary" >
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
+        android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z M18,4h-2.5l-0.71-0.71C14.61,3.11,14.35,3,14.09,
+        3H9.9C9.64,3,9.38,3.11,9.2,3.29L8.49,4h-2.5c-0.55,0-1,0.45-1,1s0.45,1,1,1h12c0.55,0,1-0.45,1-1C19,4.45,18.55,4,18,4L18,4z"/>
 </vector>
diff --git a/res/drawable/ic_wallpaper.xml b/res/drawable/ic_wallpaper.xml
index 30f6d1a..9e9222f 100644
--- a/res/drawable/ic_wallpaper.xml
+++ b/res/drawable/ic_wallpaper.xml
@@ -20,5 +20,10 @@
         android:viewportHeight="48.0">
     <path
         android:fillColor="?android:attr/textColorPrimary"
-        android:pathData="M8 8h14V4H8C5.79 4 4 5.79 4 8v14h4V8zm12 18l-8 10h24l-6-8-4.06 5.42L20 26zm14-9c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3 3-1.34 3-3zm6-13H26v4h14v14h4V8c0-2.21-1.79-4-4-4zm0 36H26v4h14c2.21 0 4-1.79 4-4V26h-4v14zM8 26H4v14c0 2.21 1.79 4 4 4h14v-4H8V26z"/>
+        android:pathData="M8,8h13c0.56,0,1-0.44,1-1V5c0-0.56-0.44-1-1-1H8C5.8,4,4,5.8,4,8v13c0,0.56,0.44,1,1,1h2c0.56,0,1-0.44,
+        1-1V8zM18.44,27.96L12,36h24l-4.4-5.86c-0.8-1.06-2.4-1.06-3.2,0l-2.46,3.28l-4.38-5.46C20.76,26.96,19.24,26.96,18.44,27.96z M34,
+        17c0-1.66-1.34-3-3-3s-3,1.34-3,3s1.34,3,3,3S34,18.66,34,17z M40,4H27c-0.56,0-1,0.44-1,1v2c0,0.56,0.44,1,1,1h13v13c0,
+        0.56,0.44,1,1,1h2c0.56,0,1-0.44,1-1V8C44,5.8,42.2,4,40,4z M40,40H27c-0.56,0-1,0.44-1,1v2c0,0.56,0.44,1,1,1h13c2.2,
+        0,4-1.8,4-4V27c0-0.56-0.44-1-1-1h-2c-0.56,0-1,0.44-1,1V40z M7,26H5c-0.56,0-1,0.44-1,1v13c0,2.2,1.8,4,4,4h13c0.56,0,1-0.44,
+        1-1v-2c0-0.56-0.44-1-1-1H8V27C8,26.44,7.56,26,7,26z"/>
 </vector>
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index cde6540..4d80aac 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -24,6 +24,7 @@
 
     <com.android.launcher3.folder.FolderPagedView
         android:id="@+id/folder_content"
+        android:clipToPadding="false"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:paddingLeft="8dp"
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 2063f32..e91f966 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -24,6 +24,7 @@
 
     <com.android.launcher3.folder.FolderPagedView
         android:id="@+id/folder_content"
+        android:clipToPadding="false"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:paddingLeft="8dp"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index b7189d1..27992ce 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -130,6 +130,6 @@
         <attr name="android:src" />
         <attr name="android:shadowColor" />
         <attr name="android:elevation" />
-        <attr name="android:tint" />
+        <attr name="darkTintColor" format="color"/>
     </declare-styleable>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 4f7c1a7..b44a31e 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -39,4 +39,5 @@
     <color name="legacy_icon_background">#FFFFFF</color>
 
     <color name="all_apps_bg_hand_fill">#E5E5E5</color>
+    <color name="all_apps_bg_hand_fill_dark">#9AA0A6</color>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 594c7db..b982136 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -156,4 +156,15 @@
     <style name="TextTitle">
         <item name="android:fontFamily">sans-serif</item>
     </style>
+
+    <style name="AllAppsEmptySearchBackground">
+        <item name="android:colorPrimary">#E0E0E0</item>
+        <item name="android:colorControlHighlight">#BDBDBD</item>
+        <item name="android:colorForeground">@color/all_apps_bg_hand_fill</item>
+    </style>
+    <style name="AllAppsEmptySearchBackground.Dark">
+        <item name="android:colorPrimary">#9AA0A6</item>
+        <item name="android:colorControlHighlight">#DFE1E5</item>
+        <item name="android:colorForeground">@color/all_apps_bg_hand_fill_dark</item>
+    </style>
 </resources>
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 08cd955..2b59ede 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -22,11 +22,13 @@
 import android.view.View.AccessibilityDelegate;
 
 import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.util.SystemUiController;
 
 public abstract class BaseActivity extends Activity {
 
     protected DeviceProfile mDeviceProfile;
     protected UserEventDispatcher mUserEventDispatcher;
+    protected SystemUiController mSystemUiController;
 
     public DeviceProfile getDeviceProfile() {
         return mDeviceProfile;
@@ -54,4 +56,11 @@
         }
         return ((BaseActivity) ((ContextWrapper) context).getBaseContext());
     }
+
+    public SystemUiController getSystemUiController() {
+        if (mSystemUiController == null) {
+            mSystemUiController = new SystemUiController(getWindow());
+        }
+        return mSystemUiController;
+    }
 }
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 8a477d8..e4a3226 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -102,8 +102,8 @@
     protected void setDrawable(int resId) {
         // We do not set the drawable in the xml as that inflates two drawables corresponding to
         // drawableLeft and drawableStart.
-        mDrawable = getResources().getDrawable(resId);
-        setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null);
+        setCompoundDrawablesRelativeWithIntrinsicBounds(resId, 0, 0, 0);
+        mDrawable = getCompoundDrawablesRelative()[0];
     }
 
     public void setDropTargetBar(DropTargetBar dropTargetBar) {
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 199baaf..1272e0a 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -36,8 +36,6 @@
 
 public class FastBitmapDrawable extends Drawable {
 
-    private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
-
     private static final float PRESSED_BRIGHTNESS = 100f / 255f;
     private static final float DISABLED_DESATURATION = 1f;
     private static final float DISABLED_BRIGHTNESS = 0.5f;
@@ -107,17 +105,6 @@
 
     @Override
     public void draw(Canvas canvas) {
-        drawInternal(canvas);
-    }
-
-    public void drawWithBrightness(Canvas canvas, float brightness) {
-        float oldBrightness = getBrightness();
-        setBrightness(brightness);
-        drawInternal(canvas);
-        setBrightness(oldBrightness);
-    }
-
-    protected void drawInternal(Canvas canvas) {
         canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
     }
 
@@ -185,6 +172,11 @@
     }
 
     @Override
+    public ColorFilter getColorFilter() {
+        return mPaint.getColorFilter();
+    }
+
+    @Override
     protected boolean onStateChange(int[] state) {
         boolean isPressed = false;
         for (int s : state) {
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index b136e7d..0370777 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -217,6 +217,10 @@
         return info == null ? null : (ShortcutInfo) info.getItemInfo().first;
     }
 
+    public static ShortcutInfo fromActivityInfo(LauncherActivityInfo info, Context context) {
+        return (ShortcutInfo) (new PendingInstallShortcutInfo(info, context).getItemInfo().first);
+    }
+
     public static void queueShortcut(ShortcutInfoCompat info, Context context) {
         queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
     }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bb32a45..66aab43 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -126,6 +126,7 @@
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.PendingRequestArgs;
+import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.TestingUtils;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.Thunk;
@@ -470,9 +471,8 @@
         // Listen for broadcasts screen off
         registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
 
-        if (Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)) {
-            activateLightSystemBars(true, true, true);
-        }
+        getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
+                Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
     }
 
     @Override
@@ -519,36 +519,6 @@
         }
     }
 
-    /**
-     * Sets the status and/or nav bar to be light or not. Light status bar means dark icons.
-     * @param isLight make sure the system bar is light.
-     * @param statusBar if true, make the status bar theme match the isLight param.
-     * @param navBar if true, make the nav bar theme match the isLight param.
-     */
-    public void activateLightSystemBars(boolean isLight, boolean statusBar, boolean navBar) {
-        int oldSystemUiFlags = getWindow().getDecorView().getSystemUiVisibility();
-        int newSystemUiFlags = oldSystemUiFlags;
-        if (isLight) {
-            if (statusBar) {
-                newSystemUiFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-            }
-            if (navBar && Utilities.isAtLeastO()) {
-                newSystemUiFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
-            }
-        } else {
-            if (statusBar) {
-                newSystemUiFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
-            }
-            if (navBar && Utilities.isAtLeastO()) {
-                newSystemUiFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
-            }
-        }
-
-        if (newSystemUiFlags != oldSystemUiFlags) {
-            getWindow().getDecorView().setSystemUiVisibility(newSystemUiFlags);
-        }
-    }
-
     private LauncherCallbacks mLauncherCallbacks;
 
     public void onPostCreate(Bundle savedInstanceState) {
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index 0902b20..b7b75f8 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -26,7 +26,6 @@
 import android.preference.PreferenceFragment;
 import android.provider.Settings;
 import android.provider.Settings.System;
-import android.support.v4.os.BuildCompat;
 
 import com.android.launcher3.graphics.IconShapeOverride;
 
@@ -85,7 +84,7 @@
             }
 
             Preference iconBadgingPref = findPreference(ICON_BADGING_PREFERENCE_KEY);
-            if (!BuildCompat.isAtLeastO()) {
+            if (!Utilities.isAtLeastO()) {
                 getPreferenceScreen().removePreference(
                         findPreference(SessionCommitReceiver.ADD_ICON_PREFERENCE_KEY));
                 getPreferenceScreen().removePreference(iconBadgingPref);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index c2987f8..9100fe2 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -38,7 +38,6 @@
 import android.os.DeadObjectException;
 import android.os.PowerManager;
 import android.os.TransactionTooLargeException;
-import android.support.v4.os.BuildCompat;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextUtils;
@@ -86,7 +85,7 @@
     private static final Matrix sInverseMatrix = new Matrix();
 
     public static boolean isAtLeastO() {
-        return BuildCompat.isAtLeastO();
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
     }
 
     public static final boolean ATLEAST_NOUGAT_MR1 =
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 758f52d..7d6d184 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -432,14 +432,17 @@
 
     private RectF drawBoxWithShadow(Canvas c, int width, int height) {
         Resources res = mContext.getResources();
-        float shadowBlur = res.getDimension(R.dimen.widget_preview_shadow_blur);
-        float keyShadowDistance = res.getDimension(R.dimen.widget_preview_key_shadow_distance);
-        float corner = res.getDimension(R.dimen.widget_preview_corner_radius);
 
-        RectF bounds = new RectF(shadowBlur, shadowBlur,
-                width - shadowBlur, height - shadowBlur - keyShadowDistance);
-        ShadowGenerator.drawShadow(c, bounds, Color.WHITE, shadowBlur, keyShadowDistance, corner);
-        return bounds;
+        ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.WHITE);
+        builder.shadowBlur = res.getDimension(R.dimen.widget_preview_shadow_blur);
+        builder.radius = res.getDimension(R.dimen.widget_preview_corner_radius);
+        builder.keyShadowDistance = res.getDimension(R.dimen.widget_preview_key_shadow_distance);
+
+        builder.bounds.set(builder.shadowBlur, builder.shadowBlur,
+                width - builder.shadowBlur,
+                height - builder.shadowBlur - builder.keyShadowDistance);
+        builder.drawShadow(c);
+        return builder.bounds;
     }
 
     private Bitmap generateShortcutPreview(BaseActivity launcher, ShortcutConfigActivityInfo info,
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b955fe1..517073a 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2098,11 +2098,6 @@
     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.
-        if (!child.isInTouchMode()) {
-            return;
-        }
-
         mDragInfo = cellInfo;
         child.setVisibility(INVISIBLE);
 
diff --git a/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java b/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
index 54c5bd0..3830a93 100644
--- a/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
+++ b/src/com/android/launcher3/allapps/AllAppsBackgroundDrawable.java
@@ -23,10 +23,12 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 
 import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
 
 /**
  * This is a custom composite drawable that has a fixed virtual size and dynamically lays out its
@@ -36,7 +38,7 @@
 public class AllAppsBackgroundDrawable extends Drawable {
 
     /**
-     * A helper class to positon and orient a drawable to be drawn.
+     * A helper class to position and orient a drawable to be drawn.
      */
     protected static class TransformedImageDrawable {
         private Drawable mImage;
@@ -49,9 +51,9 @@
          * @param gravity If one of the Gravity center values, the x and y offset will take the width
          *                and height of the image into account to center the image to the offset.
          */
-        public TransformedImageDrawable(Resources res, int resourceId, float xPct, float yPct,
+        public TransformedImageDrawable(Context context, int resourceId, float xPct, float yPct,
                 int gravity) {
-            mImage = res.getDrawable(resourceId);
+            mImage = context.getDrawable(resourceId);
             mXPercent = xPct;
             mYPercent = yPct;
             mGravity = gravity;
@@ -98,19 +100,24 @@
 
     public AllAppsBackgroundDrawable(Context context) {
         Resources res = context.getResources();
-        mHand = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_hand,
-                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.2f, Gravity.CENTER_HORIZONTAL);
-        mIcons[2] = new TransformedImageDrawable(res, R.drawable.ic_all_apps_bg_icon_3,
-                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);
         mHeight = res.getDimensionPixelSize(R.dimen.all_apps_background_canvas_height);
+
+        context = new ContextThemeWrapper(context,
+                Themes.getAttrBoolean(context, R.attr.isMainColorDark)
+                        ? R.style.AllAppsEmptySearchBackground_Dark
+                        : R.style.AllAppsEmptySearchBackground);
+        mHand = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_hand,
+                0.575f, 0.f, Gravity.CENTER_HORIZONTAL);
+        mIcons = new TransformedImageDrawable[4];
+        mIcons[0] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_1,
+                0.375f, 0, Gravity.CENTER_HORIZONTAL);
+        mIcons[1] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_2,
+                0.3125f, 0.2f, Gravity.CENTER_HORIZONTAL);
+        mIcons[2] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_3,
+                0.475f, 0.26f, Gravity.CENTER_HORIZONTAL);
+        mIcons[3] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_4,
+                0.7f, 0.125f, Gravity.CENTER_HORIZONTAL);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 051c161..4954e0c 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -299,10 +299,7 @@
 
     @Override
     public boolean onLongClick(final View v) {
-        // Return early if this is not initiated from a touch
-        if (!v.isInTouchMode()) return false;
         // When we have exited all apps or are in transition, disregard long clicks
-
         if (!mLauncher.isAppsViewVisible() ||
                 mLauncher.getWorkspace().isSwitchingState()) return false;
         // Return if global dragging is not enabled or we are already dragging
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2d8310b..4d112c6 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -28,6 +28,7 @@
 import com.android.launcher3.graphics.ScrimView;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.TouchController;
 
@@ -48,7 +49,7 @@
     private static final boolean DBG = false;
 
     private final Interpolator mWorkspaceAccelnterpolator = new AccelerateInterpolator(2f);
-    private final Interpolator mHotseatAccelInterpolator = new AccelerateInterpolator(.5f);
+    private final Interpolator mHotseatAccelInterpolator = new AccelerateInterpolator(1.5f);
     private final Interpolator mDecelInterpolator = new DecelerateInterpolator(3f);
     private final Interpolator mFastOutSlowInInterpolator = new FastOutSlowInInterpolator();
     private final VerticalPullDetector.ScrollInterpolator mScrollInterpolator
@@ -71,7 +72,6 @@
     private final VerticalPullDetector mDetector;
     private final ArgbEvaluator mEvaluator;
     private final boolean mIsDarkTheme;
-    private final boolean mIsWorkspaceDarkText;
 
     // Animation in this class is controlled by a single variable {@link mProgress}.
     // Visually, it represents top y coordinate of the all apps container if multiplied with
@@ -114,7 +114,6 @@
         mEvaluator = new ArgbEvaluator();
         mAllAppsBackgroundColor = Themes.getAttrColor(l, android.R.attr.colorPrimary);
         mIsDarkTheme = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark);
-        mIsWorkspaceDarkText = Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText);
     }
 
     @Override
@@ -278,15 +277,21 @@
     }
 
     private void updateLightStatusBar(float shift) {
-        // Do not modify status bar in dark theme or on landscape as all apps is not full bleed.
-        if (mIsDarkTheme || mIsWorkspaceDarkText || (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS
-                && mLauncher.getDeviceProfile().isVerticalBarLayout())) {
+        // Do not modify status bar on landscape as all apps is not full bleed.
+        if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS
+                && mLauncher.getDeviceProfile().isVerticalBarLayout()) {
             return;
         }
-        // Use a light status bar (dark icons) if all apps is behind at least half of the status
-        // bar. If the status bar is already light due to wallpaper extraction, keep it that way.
-        boolean forceLight = shift <= mStatusBarHeight / 2;
-        mLauncher.activateLightSystemBars(forceLight, true /* statusBar */, true /* navBar */);
+
+        // Use a light system UI (dark icons) if all apps is behind at least half of the status bar.
+        boolean forceChange = shift <= mStatusBarHeight / 2;
+        if (forceChange) {
+            mLauncher.getSystemUiController().updateUiState(
+                    SystemUiController.UI_STATE_ALL_APPS, !mIsDarkTheme);
+        } else {
+            mLauncher.getSystemUiController().updateUiState(
+                    SystemUiController.UI_STATE_ALL_APPS, 0);
+        }
     }
 
     private void updateAllAppsBg(float progress) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index b84c627..7bf6651 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -621,6 +621,10 @@
         return result;
     }
 
+    public AppInfo findApp(ComponentKey key) {
+        return mComponentToAppMap.get(key);
+    }
+
     /**
      * Returns the cached section name for the given title, recomputing and updating the cache if
      * the title has no cached section name.
diff --git a/src/com/android/launcher3/allapps/VerticalPullDetector.java b/src/com/android/launcher3/allapps/VerticalPullDetector.java
index 7800c01..13c4f63 100644
--- a/src/com/android/launcher3/allapps/VerticalPullDetector.java
+++ b/src/com/android/launcher3/allapps/VerticalPullDetector.java
@@ -17,7 +17,7 @@
     private static final boolean DBG = false;
     private static final String TAG = "VerticalPullDetector";
 
-    private float mTouchSlop;
+    private final float mTouchSlop;
 
     private int mScrollConditions;
     public static final int DIRECTION_UP = 1 << 0;
@@ -47,8 +47,6 @@
         SETTLING       // onDragEnd
     }
 
-    ;
-
     //------------------- ScrollState transition diagram -----------------------------------
     //
     // IDLE ->      (mDisplacement > mTouchSlop) -> DRAGGING
@@ -110,7 +108,7 @@
     private boolean mIgnoreSlopWhenSettling;
 
     /* Client of this gesture detector can register a callback. */
-    Listener mListener;
+    private Listener mListener;
 
     public void setListener(Listener l) {
         mListener = l;
diff --git a/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java b/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java
index d01b26c..7c5fa1c 100644
--- a/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java
+++ b/src/com/android/launcher3/anim/RoundedRectRevealOutlineProvider.java
@@ -56,7 +56,7 @@
 
     @Override
     public boolean shouldRemoveElevationDuringAnimation() {
-        return false;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java
index ba1977a..c2cc215 100644
--- a/src/com/android/launcher3/badge/BadgeRenderer.java
+++ b/src/com/android/launcher3/badge/BadgeRenderer.java
@@ -107,7 +107,8 @@
         // Lazily load the background with shadow.
         Bitmap backgroundWithShadow = mBackgroundsWithShadow.get(numChars);
         if (backgroundWithShadow == null) {
-            backgroundWithShadow = ShadowGenerator.createPillWithShadow(Color.WHITE, width, mSize);
+            backgroundWithShadow = new ShadowGenerator.Builder(Color.WHITE)
+                    .setupBlurForSize(mSize).createPill(width, mSize);
             mBackgroundsWithShadow.put(numChars, backgroundWithShadow);
         }
         canvas.save(Canvas.MATRIX_SAVE_FLAG);
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index 647c315..cc3e5a7 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -29,23 +29,22 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.os.UserHandle;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-
+import android.util.ArrayMap;
 import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVL;
 import com.android.launcher3.shortcuts.ShortcutInfoCompat;
 import com.android.launcher3.util.PackageUserKey;
-
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class LauncherAppsCompatVL extends LauncherAppsCompat {
 
     protected final LauncherApps mLauncherApps;
     protected final Context mContext;
 
-    private Map<OnAppsChangedCallbackCompat, WrappedCallback> mCallbacks = new HashMap<>();
+    private final ArrayMap<OnAppsChangedCallbackCompat, WrappedCallback> mCallbacks =
+        new ArrayMap<>();
 
     LauncherAppsCompatVL(Context context) {
         mContext = context;
@@ -131,43 +130,52 @@
     }
 
     private static class WrappedCallback extends LauncherApps.Callback {
-        private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
+        private final LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
 
         public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
             mCallback = callback;
         }
 
+        @Override
         public void onPackageRemoved(String packageName, UserHandle user) {
             mCallback.onPackageRemoved(packageName, user);
         }
 
+        @Override
         public void onPackageAdded(String packageName, UserHandle user) {
             mCallback.onPackageAdded(packageName, user);
         }
 
+        @Override
         public void onPackageChanged(String packageName, UserHandle user) {
             mCallback.onPackageChanged(packageName, user);
         }
 
+        @Override
         public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
             mCallback.onPackagesAvailable(packageNames, user, replacing);
         }
 
+        @Override
         public void onPackagesUnavailable(String[] packageNames, UserHandle user,
                 boolean replacing) {
             mCallback.onPackagesUnavailable(packageNames, user, replacing);
         }
 
+        @Override
         public void onPackagesSuspended(String[] packageNames, UserHandle user) {
             mCallback.onPackagesSuspended(packageNames, user);
         }
 
+        @Override
         public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
             mCallback.onPackagesUnsuspended(packageNames, user);
         }
 
-        public void onShortcutsChanged(String packageName, List<ShortcutInfo> shortcuts,
-                UserHandle user) {
+        @Override
+        public void onShortcutsChanged(@NonNull String packageName,
+            @NonNull List<ShortcutInfo> shortcuts,
+            @NonNull UserHandle user) {
             List<ShortcutInfoCompat> shortcutInfoCompats = new ArrayList<>(shortcuts.size());
             for (ShortcutInfo shortcutInfo : shortcuts) {
                 shortcutInfoCompats.add(new ShortcutInfoCompat(shortcutInfo));
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index 6bdc627..31c0087 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -125,7 +125,7 @@
     }
 
     @TargetApi(26)
-    static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
+    public static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
 
         private final LauncherActivityInfo mInfo;
 
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 29789c8..01893bd 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -84,6 +84,8 @@
     private int mPendingBindWidgetId;
     private Bundle mWidgetOptions;
 
+    private boolean mFinishOnPause = false;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -163,6 +165,7 @@
 
         startActivity(homeIntent,
                 ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out).toBundle());
+        mFinishOnPause = true;
 
         // Start a system drag and drop. We use a transparent bitmap as preview for system drag
         // as the preview is handled internally by launcher.
@@ -182,6 +185,14 @@
         return false;
     }
 
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mFinishOnPause) {
+            finish();
+        }
+    }
+
     private void setupShortcut() {
         PinShortcutRequestActivityInfo shortcutInfo =
                 new PinShortcutRequestActivityInfo(mRequest, this);
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
new file mode 100644
index 0000000..d0f2629
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.DragEvent;
+import android.view.View;
+
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.widget.PendingItemDragHelper;
+
+import java.util.UUID;
+
+/**
+ * {@link DragSource} for handling drop from a different window.
+ */
+public abstract class BaseItemDragListener implements
+        View.OnDragListener, DragSource, DragOptions.PreDragCondition {
+
+    private static final String TAG = "BaseItemDragListener";
+
+    private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
+    public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
+
+    // Position of preview relative to the touch location
+    private final Rect mPreviewRect;
+
+    private final int mPreviewBitmapWidth;
+    private final int mPreviewViewWidth;
+
+    // Randomly generated id used to verify the drag event.
+    private final String mId;
+
+    protected Launcher mLauncher;
+    private DragController mDragController;
+    private long mDragStartTime;
+
+    public BaseItemDragListener(Rect previewRect, int previewBitmapWidth, int previewViewWidth) {
+        mPreviewRect = previewRect;
+        mPreviewBitmapWidth = previewBitmapWidth;
+        mPreviewViewWidth = previewViewWidth;
+        mId = UUID.randomUUID().toString();
+    }
+
+    protected BaseItemDragListener(Parcel parcel) {
+        mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
+        mPreviewBitmapWidth = parcel.readInt();
+        mPreviewViewWidth = parcel.readInt();
+        mId = parcel.readString();
+    }
+
+    protected void writeToParcel(Parcel parcel, int i) {
+        mPreviewRect.writeToParcel(parcel, i);
+        parcel.writeInt(mPreviewBitmapWidth);
+        parcel.writeInt(mPreviewViewWidth);
+        parcel.writeString(mId);
+    }
+
+    public String getMimeType() {
+        return MIME_TYPE_PREFIX + mId;
+    }
+
+    public void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+        mDragController = launcher.getDragController();
+    }
+
+    @Override
+    public boolean onDrag(View view, DragEvent event) {
+        if (mLauncher == null || mDragController == null) {
+            postCleanup();
+            return false;
+        }
+        if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
+            if (onDragStart(event)) {
+                return true;
+            } else {
+                postCleanup();
+                return false;
+            }
+        }
+        return mDragController.onDragEvent(mDragStartTime, event);
+    }
+
+    protected boolean onDragStart(DragEvent event) {
+        ClipDescription desc =  event.getClipDescription();
+        if (desc == null || !desc.hasMimeType(getMimeType())) {
+            Log.e(TAG, "Someone started a dragAndDrop before us.");
+            return false;
+        }
+
+        Point downPos = new Point((int) event.getX(), (int) event.getY());
+        DragOptions options = new DragOptions();
+        options.systemDndStartPoint = downPos;
+        options.preDragCondition = this;
+
+        // We use drag event position as the screenPos for the preview image. Since mPreviewRect
+        // already includes the view position relative to the drag event on the source window,
+        // and the absolute position (position relative to the screen) of drag event is same
+        // across windows, using drag position here give a good estimate for relative position
+        // to source window.
+        createDragHelper().startDrag(new Rect(mPreviewRect),
+                mPreviewBitmapWidth, mPreviewViewWidth, downPos,  this, options);
+        mDragStartTime = SystemClock.uptimeMillis();
+        return true;
+    }
+
+    protected abstract PendingItemDragHelper createDragHelper();
+
+    @Override
+    public boolean shouldStartDrag(double distanceDragged) {
+        // Stay in pre-drag mode, if workspace is locked.
+        return !mLauncher.isWorkspaceLocked();
+    }
+
+    @Override
+    public void onPreDragStart(DropTarget.DragObject dragObject) {
+        // The predrag starts when the workspace is not yet loaded. In some cases we set
+        // the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
+        // dragView from being visible. Instead just skip the fade-in animation here.
+        mLauncher.getDragLayer().setAlpha(1);
+
+        dragObject.dragView.setColor(
+                mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
+    }
+
+    @Override
+    public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
+        if (dragStarted) {
+            dragObject.dragView.setColor(0);
+        }
+    }
+
+    @Override
+    public boolean supportsAppInfoDropTarget() {
+        return false;
+    }
+
+    @Override
+    public boolean supportsDeleteDropTarget() {
+        return false;
+    }
+
+    @Override
+    public float getIntrinsicIconScaleFactor() {
+        return 1f;
+    }
+
+    @Override
+    public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
+            boolean success) {
+        if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
+                !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
+            // Exit spring loaded mode if we have not successfully dropped or have not handled the
+            // drop in Workspace
+            mLauncher.exitSpringLoadedDragModeDelayed(true,
+                    Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+        }
+
+        if (!success) {
+            d.deferDragViewCleanupPostAnimation = false;
+        }
+        postCleanup();
+    }
+
+    private void postCleanup() {
+        if (mLauncher != null) {
+            // Remove any drag params from the launcher intent since the drag operation is complete.
+            Intent newIntent = new Intent(mLauncher.getIntent());
+            newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
+            mLauncher.setIntent(newIntent);
+        }
+
+        new Handler(Looper.getMainLooper()).post(new Runnable() {
+            @Override
+            public void run() {
+                removeListener();
+            }
+        });
+    }
+
+    public void removeListener() {
+        if (mLauncher != null) {
+            mLauncher.getDragLayer().setOnDragListener(null);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 9c6b956..ab2f100 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -16,15 +16,20 @@
 
 package com.android.launcher3.dragndrop;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.FloatArrayEvaluator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.annotation.SuppressLint;
-import android.content.pm.PackageManager;
+import android.annotation.TargetApi;
+import android.content.pm.LauncherActivityInfo;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Matrix;
@@ -33,7 +38,10 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.support.animation.DynamicAnimation;
@@ -44,20 +52,29 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.ShortcutConfigActivityInfo;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.IconNormalizer;
+import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.PendingAddShortcutInfo;
 
 import java.util.Arrays;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import java.util.List;
 
 public class DragView extends FrameLayout {
     public static final int COLOR_CHANGE_DURATION = 120;
@@ -100,9 +117,7 @@
     private SpringAnimation mSpringX, mSpringY;
     private ImageView mFgImageView, mBgImageView;
     private Path mScaledMaskPath;
-    // TODO: figure out if there is smarter way to retrieve these two constants below
-    private final static float ADAPTIVE_ICON_SCALE = .731121626f;
-    private final static float ADAPTIVE_ICON_MASK_SCALE = 1.165f; //1.185f;
+    private Drawable mBadge;
 
     // Following three values are fine tuned with motion ux designer
     private final static int STIFFNESS = 4000;
@@ -185,12 +200,13 @@
     /**
      * Initialize {@code #mIconDrawable} only if the icon type is app icon (not shortcut or folder).
      */
+    @TargetApi(Build.VERSION_CODES.O)
     public void setItemInfo(final ItemInfo info) {
         if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.isAtLeastO())) {
             return;
         }
-        if (!(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
-                || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)) {
+        if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
+                info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
             return;
         }
         // Load the adaptive icon on a background thread and add the view in ui thread.
@@ -198,40 +214,123 @@
         new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
             @Override
             public void run() {
-                PackageManager pm = (mLauncher).getPackageManager();
-                try {
-                    Drawable dr = pm.getActivityIcon(info.getTargetComponent());
-                    if (dr instanceof AdaptiveIconDrawable) {
-                        int w = mBitmap.getWidth();
-                        int h = mBitmap.getHeight();
-                        AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
-                        adaptiveIcon.setBounds(0, 0, w, h);
-                        setupMaskPath(adaptiveIcon);
-                        mFgImageView = setupImageView(adaptiveIcon.getForeground());
-                        mBgImageView = setupImageView(adaptiveIcon.getBackground());
-                        mSpringX = setupSpringAnimation(-w/4, w/4, DynamicAnimation.TRANSLATION_X);
-                        mSpringY = setupSpringAnimation(-h/4, h/4, DynamicAnimation.TRANSLATION_Y);
+                LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
+                Object[] outObj = new Object[1];
+                Drawable dr = getFullDrawable(info, appState, outObj);
 
-                        new Handler(Looper.getMainLooper()).post(new Runnable() {
-                            @Override
-                            public void run() {
-                                addView(mBgImageView);
-                                addView(mFgImageView);
-                                setWillNotDraw(true);
+                if (dr instanceof AdaptiveIconDrawable) {
+                    int w = mBitmap.getWidth();
+                    int h = mBitmap.getHeight();
+                    AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
+                    adaptiveIcon.setBounds(0, 0, w, h);
+                    float blurSizeOutline = mLauncher.getResources()
+                            .getDimension(R.dimen.blur_size_medium_outline);
+                    float normalizationScale = IconNormalizer.getInstance(mLauncher)
+                            .getScale(adaptiveIcon, null, null, null) * ((w - blurSizeOutline) / w);
+
+                    final Path mask = getMaskPath(adaptiveIcon, normalizationScale);
+                    mFgImageView = setupImageView(adaptiveIcon.getForeground(), normalizationScale);
+                    mBgImageView = setupImageView(adaptiveIcon.getBackground(), normalizationScale);
+                    mSpringX = setupSpringAnimation(-w/4, w/4, DynamicAnimation.TRANSLATION_X);
+                    mSpringY = setupSpringAnimation(-h/4, h/4, DynamicAnimation.TRANSLATION_Y);
+
+                    mBadge = getBadge(info, appState, outObj[0]);
+                    int blurMargin = (int) blurSizeOutline / 2;
+                    mBadge.setBounds(blurMargin, blurMargin, w - blurMargin, h - blurMargin);
+
+                    new Handler(Looper.getMainLooper()).post(new Runnable() {
+                        @Override
+                        public void run() {
+                            // Assign the variable on the UI thread to avoid race conditions.
+                            mScaledMaskPath = mask;
+                            addView(mBgImageView);
+                            addView(mFgImageView);
+                            setWillNotDraw(true);
+
+                            if (info.isDisabled()) {
+                                FastBitmapDrawable d = new FastBitmapDrawable(null);
+                                d.setIsDisabled(true);
+                                ColorFilter cf = d.getColorFilter();
+                                mBgImageView.setColorFilter(cf);
+                                mFgImageView.setColorFilter(cf);
+                                mBadge.setColorFilter(cf);
                             }
-                        });
-                    }
-                } catch (PackageManager.NameNotFoundException e) { }
+                        }
+                    });
+                }
             }});
     }
 
-    private ImageView setupImageView(Drawable drawable) {
+    /**
+     * Returns the full drawable for {@param info}.
+     * @param outObj this is set to the internal data associated with {@param info},
+     *               eg {@link LauncherActivityInfo} or {@link ShortcutInfoCompat}.
+     */
+    private Drawable getFullDrawable(ItemInfo info, LauncherAppState appState, Object[] outObj) {
+        if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+            LauncherActivityInfo activityInfo = LauncherAppsCompat.getInstance(mLauncher)
+                    .resolveActivity(info.getIntent(), info.user);
+            outObj[0] = activityInfo;
+            return (activityInfo != null) ? appState.getIconCache()
+                    .getFullResIcon(activityInfo) : null;
+        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+            if (info instanceof PendingAddShortcutInfo) {
+                ShortcutConfigActivityInfo activityInfo =
+                        ((PendingAddShortcutInfo) info).activityInfo;
+                outObj[0] = activityInfo;
+                return activityInfo.getFullResIcon(appState.getIconCache());
+            }
+            ShortcutKey key = ShortcutKey.fromItemInfo(info);
+            DeepShortcutManager sm = DeepShortcutManager.getInstance(mLauncher);
+            List<ShortcutInfoCompat> si = sm.queryForFullDetails(
+                    key.componentName.getPackageName(), Arrays.asList(key.getId()), key.user);
+            if (si.isEmpty()) {
+                return null;
+            } else {
+                outObj[0] = si.get(0);
+                return sm.getShortcutIconDrawable(si.get(0),
+                        appState.getInvariantDeviceProfile().fillResIconDpi);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * For apps icons and shortcut icons that have badges, this method creates a drawable that can
+     * later on be rendered on top of the layers for the badges. For app icons, work profile badges
+     * can only be applied. For deep shortcuts, when dragged from the pop up container, there's no
+     * badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
+     **/
+
+    @TargetApi(Build.VERSION_CODES.O)
+    private Drawable getBadge(ItemInfo info, LauncherAppState appState, Object obj) {
+        int iconSize = appState.getInvariantDeviceProfile().iconBitmapSize;
+        if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+            if (info.id == ItemInfo.NO_ID || !(obj instanceof ShortcutInfoCompat)) {
+                // The item is not yet added on home screen.
+                return new FixedSizeEmptyDrawable(iconSize);
+            }
+            ShortcutInfoCompat si = (ShortcutInfoCompat) obj;
+            Bitmap badge = LauncherIcons.getShortcutInfoBadge(si, appState.getIconCache());
+
+            float badgeSize = mLauncher.getResources().getDimension(R.dimen.profile_badge_size);
+            float insetFraction = (iconSize - badgeSize) / iconSize;
+            return new InsetDrawable(new FastBitmapDrawable(badge),
+                    insetFraction, insetFraction, 0, 0);
+        } else {
+            return mLauncher.getPackageManager()
+                    .getUserBadgedIcon(new FixedSizeEmptyDrawable(iconSize), info.user);
+        }
+    }
+
+    private ImageView setupImageView(Drawable drawable, float normalizationScale) {
         FrameLayout.LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
         ImageView imageViewOut = new ImageView(getContext());
         imageViewOut.setLayoutParams(params);
-        imageViewOut.setScaleType(ImageView.ScaleType.CENTER);
-        imageViewOut.setScaleX(ADAPTIVE_ICON_SCALE);
-        imageViewOut.setScaleY(ADAPTIVE_ICON_SCALE);
+        imageViewOut.setScaleType(ImageView.ScaleType.FIT_XY);
+        imageViewOut.setScaleX(normalizationScale);
+        imageViewOut.setScaleY(normalizationScale);
         imageViewOut.setImageDrawable(drawable);
         return imageViewOut;
     }
@@ -246,14 +345,16 @@
         return s;
     }
 
-    private void setupMaskPath(AdaptiveIconDrawable dr) {
+    @TargetApi(Build.VERSION_CODES.O)
+    private Path getMaskPath(AdaptiveIconDrawable dr, float normalizationScale) {
         Matrix m = new Matrix();
-        m.setScale(ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
-                ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
-                dr.getBounds().centerX(),
-                dr.getBounds().centerY());
-        mScaledMaskPath = new Path();
-        dr.getIconMask().transform(m, mScaledMaskPath);
+        // Shrink very tiny bit so that the clip path is smaller than the original bitmap
+        // that has anti aliased edges and shadows.
+        float s = normalizationScale * .97f;
+        m.setScale(s, s, dr.getBounds().centerX(), dr.getBounds().centerY());
+        Path p = new Path();
+        dr.getIconMask().transform(m, p);
+        return p;
     }
 
     private void applySpring(int x, int y) {
@@ -286,10 +387,15 @@
     @Override
     protected void dispatchDraw(Canvas canvas) {
         if (mScaledMaskPath != null) {
+            int cnt = canvas.save();
             canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
             canvas.clipPath(mScaledMaskPath);
+            super.dispatchDraw(canvas);
+            canvas.restoreToCount(cnt);
+            mBadge.draw(canvas);
+        } else {
+            super.dispatchDraw(canvas);
         }
-        super.dispatchDraw(canvas);
     }
 
     /** Sets the scale of the view over the normal workspace icon size. */
@@ -535,4 +641,24 @@
     public float getInitialScale() {
         return mInitialScale;
     }
+
+    private static class FixedSizeEmptyDrawable extends ColorDrawable {
+
+        private final int mSize;
+
+        public FixedSizeEmptyDrawable(int size) {
+            super(Color.TRANSPARENT);
+            mSize = size;
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mSize;
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mSize;
+        }
+    }
 }
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index f9f4e50..c8d3890 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -18,89 +18,49 @@
 
 import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
-import android.content.ClipDescription;
 import android.content.Intent;
 import android.content.pm.LauncherApps.PinItemRequest;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.Log;
 import android.view.DragEvent;
 import android.view.View;
 import android.widget.RemoteViews;
 
-import com.android.launcher3.DeleteDropTarget;
 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;
 import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.folder.Folder;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.PendingItemDragHelper;
 import com.android.launcher3.widget.WidgetAddFlowHandler;
 
-import java.util.UUID;
-
 /**
  * {@link DragSource} for handling drop from a different window. This object is initialized
  * in the source window and is passed on to the Launcher activity as an Intent extra.
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class PinItemDragListener
-        implements Parcelable, View.OnDragListener, DragSource, DragOptions.PreDragCondition {
+public class PinItemDragListener extends BaseItemDragListener implements Parcelable {
 
-    private static final String TAG = "PinItemDragListener";
-
-    private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
     public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
 
     private final PinItemRequest mRequest;
 
-    // Position of preview relative to the touch location
-    private final Rect mPreviewRect;
-
-    private final int mPreviewBitmapWidth;
-    private final int mPreviewViewWidth;
-
-    // Randomly generated id used to verify the drag event.
-    private final String mId;
-
-    private Launcher mLauncher;
-    private DragController mDragController;
-    private long mDragStartTime;
-
     public PinItemDragListener(PinItemRequest request, Rect previewRect,
             int previewBitmapWidth, int previewViewWidth) {
+        super(previewRect, previewBitmapWidth, previewViewWidth);
         mRequest = request;
-        mPreviewRect = previewRect;
-        mPreviewBitmapWidth = previewBitmapWidth;
-        mPreviewViewWidth = previewViewWidth;
-        mId = UUID.randomUUID().toString();
     }
 
     private PinItemDragListener(Parcel parcel) {
+        super(parcel);
         mRequest = PinItemRequest.CREATOR.createFromParcel(parcel);
-        mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
-        mPreviewBitmapWidth = parcel.readInt();
-        mPreviewViewWidth = parcel.readInt();
-        mId = parcel.readString();
-    }
-
-    public String getMimeType() {
-        return MIME_TYPE_PREFIX + mId;
     }
 
     @Override
@@ -110,45 +70,20 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int i) {
+        super.writeToParcel(parcel, i);
         mRequest.writeToParcel(parcel, i);
-        mPreviewRect.writeToParcel(parcel, i);
-        parcel.writeInt(mPreviewBitmapWidth);
-        parcel.writeInt(mPreviewViewWidth);
-        parcel.writeString(mId);
-    }
-
-    public void setLauncher(Launcher launcher) {
-        mLauncher = launcher;
-        mDragController = launcher.getDragController();
     }
 
     @Override
-    public boolean onDrag(View view, DragEvent event) {
-        if (mLauncher == null || mDragController == null) {
-            postCleanup();
-            return false;
-        }
-        if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
-            if (onDragStart(event)) {
-                return true;
-            } else {
-                postCleanup();
-                return false;
-            }
-        }
-        return mDragController.onDragEvent(mDragStartTime, event);
-    }
-
-    private boolean onDragStart(DragEvent event) {
+    protected boolean onDragStart(DragEvent event) {
         if (!mRequest.isValid()) {
             return false;
         }
-        ClipDescription desc =  event.getClipDescription();
-        if (desc == null || !desc.hasMimeType(getMimeType())) {
-            Log.e(TAG, "Someone started a dragAndDrop before us.");
-            return false;
-        }
+        return super.onDragStart(event);
+    }
 
+    @Override
+    protected PendingItemDragHelper createDragHelper() {
         final PendingAddItemInfo item;
         if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
             item = new PendingAddShortcutInfo(
@@ -170,109 +105,17 @@
         View view = new View(mLauncher);
         view.setTag(item);
 
-        Point downPos = new Point((int) event.getX(), (int) event.getY());
-        DragOptions options = new DragOptions();
-        options.systemDndStartPoint = downPos;
-        options.preDragCondition = this;
-
-        // We use drag event position as the screenPos for the preview image. Since mPreviewRect
-        // already includes the view position relative to the drag event on the source window,
-        // and the absolute position (position relative to the screen) of drag event is same
-        // across windows, using drag position here give a good estimate for relative position
-        // to source window.
         PendingItemDragHelper dragHelper = new PendingItemDragHelper(view);
         if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_APPWIDGET) {
             dragHelper.setPreview(getPreview(mRequest));
         }
-
-        dragHelper.startDrag(new Rect(mPreviewRect),
-                mPreviewBitmapWidth, mPreviewViewWidth, downPos,  this, options);
-        mDragStartTime = SystemClock.uptimeMillis();
-        return true;
-    }
-
-    @Override
-    public boolean shouldStartDrag(double distanceDragged) {
-        // Stay in pre-drag mode, if workspace is locked.
-        return !mLauncher.isWorkspaceLocked();
-    }
-
-    @Override
-    public void onPreDragStart(DropTarget.DragObject dragObject) {
-        // The predrag starts when the workspace is not yet loaded. In some cases we set
-        // the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
-        // dragView from being visible. Instead just skip the fade-in animation here.
-        mLauncher.getDragLayer().setAlpha(1);
-
-        dragObject.dragView.setColor(
-                mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
-    }
-
-    @Override
-    public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
-        if (dragStarted) {
-            dragObject.dragView.setColor(0);
-        }
-    }
-
-    @Override
-    public boolean supportsAppInfoDropTarget() {
-        return false;
-    }
-
-    @Override
-    public boolean supportsDeleteDropTarget() {
-        return false;
-    }
-
-    @Override
-    public float getIntrinsicIconScaleFactor() {
-        return 1f;
-    }
-
-    @Override
-    public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
-            boolean success) {
-        if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
-                !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
-            // Exit spring loaded mode if we have not successfully dropped or have not handled the
-            // drop in Workspace
-            mLauncher.exitSpringLoadedDragModeDelayed(true,
-                    Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
-        }
-
-        if (!success) {
-            d.deferDragViewCleanupPostAnimation = false;
-        }
-        postCleanup();
+        return dragHelper;
     }
 
     @Override
     public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target,
             LauncherLogProto.Target targetParent) {
-        targetParent.containerType = ContainerType.PINITEM;
-    }
-
-    private void postCleanup() {
-        if (mLauncher != null) {
-            // Remove any drag params from the launcher intent since the drag operation is complete.
-            Intent newIntent = new Intent(mLauncher.getIntent());
-            newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
-            mLauncher.setIntent(newIntent);
-        }
-
-        new Handler(Looper.getMainLooper()).post(new Runnable() {
-            @Override
-            public void run() {
-                removeListener();
-            }
-        });
-    }
-
-    public void removeListener() {
-        if (mLauncher != null) {
-            mLauncher.getDragLayer().setOnDragListener(null);
-        }
+        targetParent.containerType = LauncherLogProto.ContainerType.PINITEM;
     }
 
     public static RemoteViews getPreview(PinItemRequest request) {
diff --git a/src/com/android/launcher3/dynamicui/ExtractionUtils.java b/src/com/android/launcher3/dynamicui/ExtractionUtils.java
index 92cb5dc..cc0e0be 100644
--- a/src/com/android/launcher3/dynamicui/ExtractionUtils.java
+++ b/src/com/android/launcher3/dynamicui/ExtractionUtils.java
@@ -29,6 +29,7 @@
 import android.support.v7.graphics.Palette;
 
 import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
 
 import java.util.List;
 
@@ -47,6 +48,9 @@
      * Launcher will be notified in Launcher#onSettingsChanged(String, String).
      */
     public static void startColorExtractionServiceIfNecessary(final Context context) {
+        if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+            return;
+        }
         // Run on a background thread, since the service is asynchronous anyway.
         Utilities.THREAD_POOL_EXECUTOR.execute(new Runnable() {
             @Override
@@ -60,6 +64,9 @@
 
     /** Starts the {@link ColorExtractionService} without checking the wallpaper id */
     public static void startColorExtractionService(Context context) {
+        if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+            return;
+        }
         JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
                 Context.JOB_SCHEDULER_SERVICE);
         jobScheduler.schedule(new JobInfo.Builder(Utilities.COLOR_EXTRACTION_JOB_ID,
diff --git a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
index 856a26c..512e89a 100644
--- a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
+++ b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
@@ -61,7 +61,7 @@
 
     @Override
     public void onColorsChanged(WallpaperColorsCompat colors, int which) {
-        if (which == FLAG_SYSTEM) {
+        if ((which & FLAG_SYSTEM) != 0) {
             boolean wasDarkTheme = mIsDark;
             boolean didSupportDarkText = mSupportsDarkText;
             update(colors);
diff --git a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
index 0df787a..33bf275 100644
--- a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
@@ -20,7 +20,7 @@
     private float mBaselineIconScale;
 
     @Override
-    public void init(int availableSpace, int intrinsicIconSize, boolean rtl) {
+    public void init(int availableSpace, float intrinsicIconSize, boolean rtl) {
         mAvailableSpace = availableSpace;
         mRadius = ITEM_RADIUS_SCALE_FACTOR * availableSpace / 2f;
         mIconSize = intrinsicIconSize;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index fc25c9a..aad8123 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -283,9 +283,6 @@
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
             ShortcutInfo item = (ShortcutInfo) tag;
-            if (!v.isInTouchMode()) {
-                return false;
-            }
 
             mEmptyCellRank = item.rank;
             mCurrentDragView = v;
@@ -335,6 +332,7 @@
         if (mIsExternalDrag && mDragInProgress) {
             completeDragExit();
         }
+        mDragInProgress = false;
         mDragController.removeDragListener(this);
     }
 
@@ -791,8 +789,11 @@
         mDragController.removeDropTarget(this);
         clearFocus();
         if (mFolderIcon != null) {
-            mFolderIcon.setBackgroundVisible(true);
             mFolderIcon.setVisibility(View.VISIBLE);
+            if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
+                mFolderIcon.setBackgroundVisible(true);
+                mFolderIcon.mBackground.fadeInBackgroundShadow();
+            }
             if (wasAnimated) {
                 mFolderIcon.mBackground.animateBackgroundStroke();
                 if (mFolderIcon.hasBadge()) {
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index bb2d1a2..74e8d3b 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -221,6 +221,12 @@
                 mFolder.setTranslationY(0.0f);
                 mFolder.setScaleX(1f);
                 mFolder.setScaleY(1f);
+
+                if (mIsOpening) {
+                    getAnimator(mFolder, View.TRANSLATION_Z, -mFolder.getElevation(), 0)
+                            .setDuration(150)
+                            .start();
+                }
             }
         });
 
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index aaa19af..fa148c8 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -36,6 +36,7 @@
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
+import android.support.annotation.NonNull;
 import android.support.v4.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.util.Property;
@@ -75,6 +76,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragView;
+import com.android.launcher3.graphics.PreloadIconDrawable;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.graphics.IconPalette;
 import com.android.launcher3.util.Thunk;
@@ -115,7 +117,7 @@
 
     // These variables are all associated with the drawing of the preview; they are stored
     // as member variables for shared usage and to avoid computation on each frame
-    private int mIntrinsicIconSize = -1;
+    private float mIntrinsicIconSize = -1;
     private int mTotalWidth = -1;
     private int mPrevTopPadding = -1;
 
@@ -131,7 +133,7 @@
 
     FolderIconPreviewVerifier mPreviewVerifier;
     private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
-    private ArrayList<PreviewItemDrawingParams> mDrawingParams = new ArrayList<PreviewItemDrawingParams>();
+    private ArrayList<PreviewItemDrawingParams> mDrawingParams = new ArrayList<>();
     private Drawable mReferenceDrawable = null;
 
     private Alarm mOpenAlarm = new Alarm();
@@ -509,18 +511,12 @@
         Drawable d = params.drawable;
 
         if (d != null) {
-            mTempBounds.set(d.getBounds());
-            d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
-            if (d instanceof FastBitmapDrawable) {
-                FastBitmapDrawable fd = (FastBitmapDrawable) d;
-                fd.drawWithBrightness(canvas, params.overlayAlpha);
-            } else {
-                d.setColorFilter(Color.argb((int) (params.overlayAlpha * 255), 255, 255, 255),
-                        PorterDuff.Mode.SRC_ATOP);
-                d.draw(canvas);
-                d.clearColorFilter();
-            }
-            d.setBounds(mTempBounds);
+            Rect bounds = d.getBounds();
+            canvas.save();
+            canvas.translate(-bounds.left, -bounds.top);
+            canvas.scale(mIntrinsicIconSize / bounds.width(), mIntrinsicIconSize / bounds.height());
+            d.draw(canvas);
+            canvas.restore();
         }
         canvas.restore();
     }
@@ -555,6 +551,7 @@
         private int mBgColor;
         private float mStrokeWidth;
         private int mStrokeAlpha = MAX_BG_OPACITY;
+        private int mShadowAlpha = 255;
         private View mInvalidateDelegate;
 
         public int previewSize;
@@ -580,6 +577,7 @@
 
         ValueAnimator mScaleAnimator;
         ObjectAnimator mStrokeAlphaAnimator;
+        ObjectAnimator mShadowAnimator;
 
         private static final Property<PreviewBackground, Integer> STROKE_ALPHA =
                 new Property<PreviewBackground, Integer>(Integer.class, "strokeAlpha") {
@@ -595,6 +593,20 @@
                     }
                 };
 
+        private static final Property<PreviewBackground, Integer> SHADOW_ALPHA =
+                new Property<PreviewBackground, Integer>(Integer.class, "shadowAlpha") {
+                    @Override
+                    public Integer get(PreviewBackground previewBackground) {
+                        return previewBackground.mShadowAlpha;
+                    }
+
+                    @Override
+                    public void set(PreviewBackground previewBackground, Integer alpha) {
+                        previewBackground.mShadowAlpha = alpha;
+                        previewBackground.invalidate();
+                    }
+                };
+
         public void setup(Launcher launcher, View invalidateDelegate,
                    int availableSpace, int topPadding) {
             mInvalidateDelegate = invalidateDelegate;
@@ -692,10 +704,11 @@
             mShaderMatrix.setScale(shadowRadius, shadowRadius);
             mShaderMatrix.postTranslate(radius + offsetX, shadowRadius + offsetY);
             mShadowShader.setLocalMatrix(mShaderMatrix);
+            mPaint.setAlpha(mShadowAlpha);
             mPaint.setShader(mShadowShader);
             canvas.drawPaint(mPaint);
+            mPaint.setAlpha(255);
             mPaint.setShader(null);
-
             if (canvas.isHardwareAccelerated()) {
                 mPaint.setXfermode(mShadowPorterDuffXfermode);
                 canvas.drawCircle(radius + offsetX, radius + offsetY, radius, mPaint);
@@ -705,6 +718,22 @@
             canvas.restoreToCount(saveCount);
         }
 
+        public void fadeInBackgroundShadow() {
+            if (mShadowAnimator != null) {
+                mShadowAnimator.cancel();
+            }
+            mShadowAnimator = ObjectAnimator
+                    .ofInt(this, SHADOW_ALPHA, 0, 255)
+                    .setDuration(100);
+            mShadowAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mShadowAnimator = null;
+                }
+            });
+            mShadowAnimator.start();
+        }
+
         public void animateBackgroundStroke() {
             if (mStrokeAlphaAnimator != null) {
                 mStrokeAlphaAnimator.cancel();
@@ -1072,6 +1101,16 @@
         return itemsToDisplay;
     }
 
+    @Override
+    protected boolean verifyDrawable(@NonNull Drawable who) {
+        for (int i = 0; i < mDrawingParams.size(); i++) {
+            if (mDrawingParams.get(i).drawable == who) {
+                return true;
+            }
+        }
+        return super.verifyDrawable(who);
+    }
+
     private void updateItemDrawingParams(boolean animate) {
         List<BubbleTextView> items = getItemsToDisplay();
         int nItemsInPreview = items.size();
@@ -1090,6 +1129,12 @@
             PreviewItemDrawingParams p = mDrawingParams.get(i);
             p.drawable = items.get(i).getCompoundDrawables()[1];
 
+            if (p.drawable != null && !mFolder.isOpen()) {
+                // Set the callback to FolderIcon as it is responsible to drawing the icon. The
+                // callback will be release when the folder is opened.
+                p.drawable.setCallback(this);
+            }
+
             if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
                 computePreviewItemDrawingParams(i, nItemsInPreview, p);
                 if (mReferenceDrawable == null) {
@@ -1260,7 +1305,7 @@
     public interface PreviewLayoutRule {
         PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
             PreviewItemDrawingParams params);
-        void init(int availableSpace, int intrinsicIconSize, boolean rtl);
+        void init(int availableSpace, float intrinsicIconSize, boolean rtl);
         float scaleForItem(int index, int totalNumItems);
         float getIconSize();
         int maxNumItems();
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 898a4e9..d0ac9f4 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +19,8 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Gravity;
@@ -46,7 +48,6 @@
 import com.android.launcher3.util.Thunk;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -72,7 +73,7 @@
     private final LayoutInflater mInflater;
     private final ViewGroupFocusHelper mFocusIndicatorHelper;
 
-    @Thunk final HashMap<View, Runnable> mPendingAnimations = new HashMap<>();
+    @Thunk final ArrayMap<View, Runnable> mPendingAnimations = new ArrayMap<>();
 
     @ViewDebug.ExportedProperty(category = "launcher")
     private final int mMaxCountX;
@@ -111,7 +112,7 @@
     public void setFolder(Folder folder) {
         mFolder = folder;
         mKeyListener = new PagedFolderKeyEventListener(folder);
-        mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator);
+        mPageIndicator = folder.findViewById(R.id.folder_page_indicator);
         initParentViews(folder);
     }
 
@@ -185,8 +186,8 @@
      * @return list of items that could not be bound, probably because we hit the max size limit.
      */
     public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
-        ArrayList<View> icons = new ArrayList<View>();
-        ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
+        ArrayList<View> icons = new ArrayList<>();
+        ArrayList<ShortcutInfo> extra = new ArrayList<>();
 
         for (ShortcutInfo item : items) {
             if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) {
@@ -320,7 +321,7 @@
 
     @SuppressLint("RtlHardcoded")
     private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) {
-        ArrayList<CellLayout> pages = new ArrayList<CellLayout>();
+        ArrayList<CellLayout> pages = new ArrayList<>();
         for (int i = 0; i < getChildCount(); i++) {
             CellLayout page = (CellLayout) getChildAt(i);
             page.removeAllViews();
@@ -527,7 +528,7 @@
      */
     public void completePendingPageChanges() {
         if (!mPendingAnimations.isEmpty()) {
-            HashMap<View, Runnable> pendingViews = new HashMap<>(mPendingAnimations);
+            ArrayMap<View, Runnable> pendingViews = new ArrayMap<>(mPendingAnimations);
             for (Map.Entry<View, Runnable> e : pendingViews.entrySet()) {
                 e.getKey().animate().cancel();
                 e.getValue().run();
@@ -556,7 +557,14 @@
         if (page != null) {
             ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
             for (int i = parent.getChildCount() - 1; i >= 0; i--) {
-                ((BubbleTextView) parent.getChildAt(i)).verifyHighRes();
+                BubbleTextView icon = ((BubbleTextView) parent.getChildAt(i));
+                icon.verifyHighRes();
+                // Set the callback back to the actual icon, in case
+                // it was captured by the FolderIcon
+                Drawable d = icon.getCompoundDrawables()[1];
+                if (d != null) {
+                    d.setCallback(icon);
+                }
             }
         }
     }
diff --git a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
index 12bca5f..1ece278 100644
--- a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
@@ -35,7 +35,7 @@
     private float mMaxPerspectiveShift;
 
     @Override
-    public void init(int availableSpace, int intrinsicIconSize, boolean rtl) {
+    public void init(int availableSpace, float intrinsicIconSize, boolean rtl) {
         mAvailableSpaceInPreview = availableSpace;
 
         // cos(45) = 0.707  + ~= 0.1) = 0.8f
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 466b5cb..830ca82 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -328,7 +328,10 @@
             return unbadgedBitmap;
         }
         unbadgedBitmap = LauncherIcons.addShadowToIcon(unbadgedBitmap, context);
+        return badgeWithBitmap(unbadgedBitmap, getShortcutInfoBadge(shortcutInfo, cache), context);
+    }
 
+    public static Bitmap getShortcutInfoBadge(ShortcutInfoCompat shortcutInfo, IconCache cache) {
         final Bitmap badgeBitmap;
         ComponentName cn = shortcutInfo.getActivity();
         if (cn != null) {
@@ -346,7 +349,7 @@
             cache.getTitleAndIconForApp(pkgInfo, false);
             badgeBitmap = pkgInfo.iconBitmap;
         }
-        return badgeWithBitmap(unbadgedBitmap, badgeBitmap, context);
+        return badgeBitmap;
     }
 
     /**
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index deb5b63..06dc7ac 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -178,7 +178,7 @@
         Rect bounds = getBounds();
 
         canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY());
-        drawInternal(canvas);
+        super.draw(canvas);
         canvas.restoreToCount(saveCount);
     }
 
diff --git a/src/com/android/launcher3/graphics/ShadowDrawable.java b/src/com/android/launcher3/graphics/ShadowDrawable.java
index 45c1b6a..ffcedb2 100644
--- a/src/com/android/launcher3/graphics/ShadowDrawable.java
+++ b/src/com/android/launcher3/graphics/ShadowDrawable.java
@@ -17,7 +17,6 @@
 package com.android.launcher3.graphics;
 
 import android.annotation.TargetApi;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -28,7 +27,6 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.AttributeSet;
@@ -111,12 +109,11 @@
 
     @Override
     public void applyTheme(Resources.Theme t) {
-        if (mState.canApplyTheme()) {
-            // Workaround since ColorStateList does not expose applyTheme method
-            ColorDrawable cd = new ColorDrawable();
-            cd.setTintList(mState.mTintColor);
-            cd.applyTheme(t);
-
+        TypedArray ta = t.obtainStyledAttributes(new int[] {R.attr.isWorkspaceDarkText});
+        boolean isDark = ta.getBoolean(0, false);
+        ta.recycle();
+        if (mState.mIsDark != isDark) {
+            mState.mIsDark = isDark;
             mState.mLastDrawnBitmap = null;
             invalidateSelf();
         }
@@ -132,21 +129,22 @@
         d.setBounds(mState.mShadowSize, mState.mShadowSize,
                 mState.mIntrinsicWidth - mState.mShadowSize,
                 mState.mIntrinsicHeight - mState.mShadowSize);
-        if (mState.mTintColor != null) {
-            d.setTint(mState.mTintColor.getDefaultColor());
+        d.setTint(mState.mIsDark ? mState.mDarkTintColor : Color.WHITE);
+        d.draw(canvas);
+
+        // Do not draw shadow on dark theme
+        if (!mState.mIsDark) {
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+            paint.setMaskFilter(new BlurMaskFilter(mState.mShadowSize, BlurMaskFilter.Blur.NORMAL));
+            int[] offset = new int[2];
+            Bitmap shadow = bitmap.extractAlpha(paint, offset);
+
+            paint.setMaskFilter(null);
+            paint.setColor(mState.mShadowColor);
+            bitmap.eraseColor(Color.TRANSPARENT);
+            canvas.drawBitmap(shadow, offset[0], offset[1], paint);
+            d.draw(canvas);
         }
-        d.draw(canvas);
-
-        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
-        paint.setMaskFilter(new BlurMaskFilter(mState.mShadowSize, BlurMaskFilter.Blur.NORMAL));
-        int[] offset = new int[2];
-        Bitmap shadow = bitmap.extractAlpha(paint, offset);
-
-        paint.setMaskFilter(null);
-        paint.setColor(mState.mShadowColor);
-        bitmap.eraseColor(Color.TRANSPARENT);
-        canvas.drawBitmap(shadow, offset[0], offset[1], paint);
-        d.draw(canvas);
 
         if (Utilities.isAtLeastO()) {
             bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
@@ -162,7 +160,6 @@
         final TypedArray a = theme == null
                 ? r.obtainAttributes(attrs, R.styleable.ShadowDrawable)
                 : theme.obtainStyledAttributes(attrs, R.styleable.ShadowDrawable, 0, 0);
-
         try {
             Drawable d = a.getDrawable(R.styleable.ShadowDrawable_android_src);
             if (d == null) {
@@ -172,7 +169,8 @@
                     R.styleable.ShadowDrawable_android_shadowColor, Color.BLACK);
             mState.mShadowSize = a.getDimensionPixelSize(
                     R.styleable.ShadowDrawable_android_elevation, 0);
-            mState.mTintColor = a.getColorStateList(R.styleable.ShadowDrawable_android_tint);
+            mState.mDarkTintColor = a.getColor(
+                    R.styleable.ShadowDrawable_darkTintColor, Color.BLACK);
 
             mState.mIntrinsicHeight = d.getIntrinsicHeight() + 2 * mState.mShadowSize;
             mState.mIntrinsicWidth = d.getIntrinsicWidth() + 2 * mState.mShadowSize;
@@ -192,8 +190,9 @@
 
         int mShadowColor;
         int mShadowSize;
-        ColorStateList mTintColor;
+        int mDarkTintColor;
 
+        boolean mIsDark;
         Bitmap mLastDrawnBitmap;
         ConstantState mChildState;
 
@@ -209,7 +208,7 @@
 
         @Override
         public boolean canApplyTheme() {
-            return mTintColor != null;
+            return true;
         }
     }
 }
diff --git a/src/com/android/launcher3/graphics/ShadowGenerator.java b/src/com/android/launcher3/graphics/ShadowGenerator.java
index 9ea11a7..fffea8e 100644
--- a/src/com/android/launcher3/graphics/ShadowGenerator.java
+++ b/src/com/android/launcher3/graphics/ShadowGenerator.java
@@ -28,7 +28,6 @@
 import android.support.v4.graphics.ColorUtils;
 
 import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.util.Preconditions;
 
 /**
  * Utility class to add shadows to bitmaps.
@@ -85,48 +84,10 @@
         return result;
     }
 
-    public static Bitmap createPillWithShadow(int rectColor, int width, int height) {
-        float shadowRadius = height * 1f / 32;
-        float shadowYOffset = height * 1f / 16;
-        return createPillWithShadow(rectColor, width, height, shadowRadius, shadowYOffset,
-                new RectF());
-    }
-
-    public static Bitmap createPillWithShadow(int rectColor, int width, int height,
-            float shadowRadius, float shadowYOffset, RectF outRect) {
-        int radius = height / 2;
-
-        int centerX = Math.round(width / 2 + shadowRadius);
-        int centerY = Math.round(radius + shadowRadius + shadowYOffset);
-        int center = Math.max(centerX, centerY);
-        int size = center * 2;
-        Bitmap result = Bitmap.createBitmap(size, size, Config.ARGB_8888);
-
-        outRect.set(0, 0, width, height);
-        outRect.offsetTo(center - width / 2, center - height / 2);
-
-        drawShadow(new Canvas(result), outRect, rectColor, shadowRadius, shadowYOffset, radius);
-        return result;
-    }
-
-    public static void drawShadow(Canvas c, RectF bounds, int color,
-            float shadowBlur, float keyShadowDistance, float radius) {
-        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
-        p.setColor(color);
-
-        // Key shadow
-        p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
-                ColorUtils.setAlphaComponent(Color.BLACK, KEY_SHADOW_ALPHA));
-        c.drawRoundRect(bounds, radius, radius, p);
-
-        // Ambient shadow
-        p.setShadowLayer(shadowBlur, 0, 0,
-                ColorUtils.setAlphaComponent(Color.BLACK, AMBIENT_SHADOW_ALPHA));
-        c.drawRoundRect(bounds, radius, radius, p);
-    }
-
     public static ShadowGenerator getInstance(Context context) {
-        Preconditions.assertNonUiThread();
+        // TODO: This currently fails as the system default icon also needs a shadow as it
+        // uses adaptive icon.
+        // Preconditions.assertNonUiThread();
         synchronized (LOCK) {
             if (sShadowGenerator == null) {
                 sShadowGenerator = new ShadowGenerator(context);
@@ -154,4 +115,58 @@
         }
         return scale;
     }
+
+    public static class Builder {
+
+        public final RectF bounds = new RectF();
+        public final int color;
+
+        public int ambientShadowAlpha = AMBIENT_SHADOW_ALPHA;
+
+        public float shadowBlur;
+
+        public float keyShadowDistance;
+        public int keyShadowAlpha = KEY_SHADOW_ALPHA;
+        public float radius;
+
+        public Builder(int color) {
+            this.color = color;
+        }
+
+        public Builder setupBlurForSize(int height) {
+            shadowBlur = height * 1f / 32;
+            keyShadowDistance = height * 1f / 16;
+            return this;
+        }
+
+        public Bitmap createPill(int width, int height) {
+            radius = height / 2;
+
+            int centerX = Math.round(width / 2 + shadowBlur);
+            int centerY = Math.round(radius + shadowBlur + keyShadowDistance);
+            int center = Math.max(centerX, centerY);
+            bounds.set(0, 0, width, height);
+            bounds.offsetTo(center - width / 2, center - height / 2);
+
+            int size = center * 2;
+            Bitmap result = Bitmap.createBitmap(size, size, Config.ARGB_8888);
+            drawShadow(new Canvas(result));
+            return result;
+        }
+
+        public void drawShadow(Canvas c) {
+            Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+            p.setColor(color);
+
+            // Key shadow
+            p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
+                    ColorUtils.setAlphaComponent(Color.BLACK, keyShadowAlpha));
+            c.drawRoundRect(bounds, radius, radius, p);
+
+            // Ambient shadow
+            p.setShadowLayer(shadowBlur, 0, 0,
+                    ColorUtils.setAlphaComponent(Color.BLACK, ambientShadowAlpha));
+            c.drawRoundRect(bounds, radius, radius, p);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 8dca699..2d9c23e 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -24,8 +24,8 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.support.annotation.Nullable;
-import android.support.v4.util.Pair;
 import android.text.TextUtils;
+import android.util.Pair;
 
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.config.FeatureFlags;
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsItemView.java b/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
index 59a0386..8785a56 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
@@ -104,8 +104,8 @@
 
     @Override
     public boolean onLongClick(View v) {
-        // Return early if this is not initiated from a touch or not the correct view
-        if (!v.isInTouchMode() || !(v.getParent() instanceof DeepShortcutView)) return false;
+        // Return early if not the correct view
+        if (!(v.getParent() instanceof DeepShortcutView)) return false;
         // Return early if global dragging is not enabled
         if (!mLauncher.isDraggingEnabled()) return false;
         // Return early if an item is already being dragged (e.g. when long-pressing two shortcuts)
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
new file mode 100644
index 0000000..6b5b095
--- /dev/null
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 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.view.View;
+import android.view.Window;
+
+import com.android.launcher3.Utilities;
+
+/**
+ * Utility class to manage various window flags to control system UI.
+ */
+public class SystemUiController {
+
+    // Various UI states in increasing order of priority
+    public static final int UI_STATE_BASE_WINDOW = 0;
+    public static final int UI_STATE_ALL_APPS = 1;
+    public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
+
+    public static final int FLAG_LIGHT_NAV = 1 << 0;
+    public static final int FLAG_DARK_NAV = 1 << 1;
+    public static final int FLAG_LIGHT_STATUS = 1 << 2;
+    public static final int FLAG_DARK_STATUS = 1 << 3;
+
+    private final Window mWindow;
+    private final int[] mStates = new int[3];
+
+    public SystemUiController(Window window) {
+        mWindow = window;
+    }
+
+    public void updateUiState(int uiState, boolean isLight) {
+        updateUiState(uiState, isLight
+                ? (FLAG_LIGHT_NAV | FLAG_LIGHT_STATUS) : (FLAG_DARK_NAV | FLAG_DARK_STATUS));
+    }
+
+    public void updateUiState(int uiState, int flags) {
+        if (mStates[uiState] == flags) {
+            return;
+        }
+        mStates[uiState] = flags;
+
+        int oldFlags = mWindow.getDecorView().getSystemUiVisibility();
+        // Apply the state flags in priority order
+        int newFlags = oldFlags;
+        for (int stateFlag : mStates) {
+            if (Utilities.isAtLeastO()) {
+                if ((stateFlag & FLAG_LIGHT_NAV) != 0) {
+                    newFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+                } else if ((stateFlag & FLAG_DARK_NAV) != 0) {
+                    newFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+                }
+            }
+
+            if ((stateFlag & FLAG_LIGHT_STATUS) != 0) {
+                newFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+            } else if ((stateFlag & FLAG_DARK_STATUS) != 0) {
+                newFlags &= ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+            }
+        }
+        if (newFlags != oldFlags) {
+            mWindow.getDecorView().setSystemUiVisibility(newFlags);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 5fe00c2..d87e7fb 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -21,7 +21,6 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Rect;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
 import android.util.AttributeSet;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
@@ -29,6 +28,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.TextView;
 
@@ -48,6 +48,7 @@
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.TouchController;
 
 import java.util.List;
@@ -69,7 +70,6 @@
     private Interpolator mFastOutSlowInInterpolator;
     private VerticalPullDetector.ScrollInterpolator mScrollInterpolator;
     private Rect mInsets;
-    private boolean mWasNavBarLight;
     private VerticalPullDetector mVerticalPullDetector;
 
     public WidgetsBottomSheet(Context context, AttributeSet attrs) {
@@ -81,7 +81,8 @@
         setWillNotDraw(false);
         mLauncher = Launcher.getLauncher(context);
         mOpenCloseAnimator = LauncherAnimUtils.ofPropertyValuesHolder(this);
-        mFastOutSlowInInterpolator = new FastOutSlowInInterpolator();
+        mFastOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
         mScrollInterpolator = new VerticalPullDetector.ScrollInterpolator();
         mInsets = new Rect();
         mVerticalPullDetector = new VerticalPullDetector(context);
@@ -103,8 +104,6 @@
 
         onWidgetsBound();
 
-        mWasNavBarLight = (mLauncher.getWindow().getDecorView().getSystemUiVisibility()
-                & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0;
         mLauncher.getDragLayer().addView(this);
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
         setTranslationY(mTranslationYClosed);
@@ -180,7 +179,8 @@
             return;
         }
         mIsOpen = true;
-        setLightNavBar(true);
+        mLauncher.getSystemUiController().updateUiState(
+                SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, SystemUiController.FLAG_LIGHT_NAV);
         if (animate) {
             mOpenCloseAnimator.setValues(new PropertyListBuilder()
                     .translationY(mTranslationYOpen).build());
@@ -211,7 +211,8 @@
                     mIsOpen = false;
                     mVerticalPullDetector.finishedScrolling();
                     ((ViewGroup) getParent()).removeView(WidgetsBottomSheet.this);
-                    setLightNavBar(mWasNavBarLight);
+                    mLauncher.getSystemUiController().updateUiState(
+                            SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0);
                 }
             });
             mOpenCloseAnimator.setInterpolator(mVerticalPullDetector.isIdleState()
@@ -219,15 +220,12 @@
             mOpenCloseAnimator.start();
         } else {
             setTranslationY(mTranslationYClosed);
-            setLightNavBar(mWasNavBarLight);
+            mLauncher.getSystemUiController().updateUiState(
+                    SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0);
             mIsOpen = false;
         }
     }
 
-    private void setLightNavBar(boolean lightNavBar) {
-        mLauncher.activateLightSystemBars(lightNavBar, false /* statusBar */, true /* navBar */);
-    }
-
     @Override
     protected boolean isOfType(@FloatingViewType int type) {
         return (type & TYPE_WIDGETS_BOTTOM_SHEET) != 0;
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 4e296bf..14a9d17 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -139,8 +139,6 @@
         if (LOGD) {
             Log.d(TAG, String.format("onLongClick [v=%s]", v));
         }
-        // Return early if this is not initiated from a touch
-        if (!v.isInTouchMode()) return false;
         // When we  are in transition, disregard long clicks
         if (mLauncher.getWorkspace().isSwitchingState()) return false;
         // Return if global dragging is not enabled
diff --git a/src_flags/com/android/launcher3/config/FeatureFlags.java b/src_flags/com/android/launcher3/config/FeatureFlags.java
index 40200c5..42a110c 100644
--- a/src_flags/com/android/launcher3/config/FeatureFlags.java
+++ b/src_flags/com/android/launcher3/config/FeatureFlags.java
@@ -37,7 +37,7 @@
     // When enabled while all-apps open, the soft input will be set to adjust resize .
     public static boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = true;
     // When enabled the promise icon is visible in all apps while installation an app.
-    public static boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = true;
+    public static boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false;
     // When enabled uses the AllAppsRadialGradientAndScrimDrawable for all apps
     public static boolean LAUNCHER3_GRADIENT_ALL_APPS = true;
     // When enabled allows use of physics based motions in the Launcher.