Merge "Revert "Lock launcher to portrait on devices less than sw720dp"" into jb-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 47278bb..dbeb7bc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -57,6 +57,7 @@
     <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
     <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
 
diff --git a/res/drawable-hdpi/widget_container_holo.9.png b/res/drawable-hdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..8c15a7c
--- /dev/null
+++ b/res/drawable-hdpi/widget_container_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_preview_tile.png b/res/drawable-hdpi/widget_preview_tile.png
new file mode 100644
index 0000000..caeddd1
--- /dev/null
+++ b/res/drawable-hdpi/widget_preview_tile.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_container_holo.9.png b/res/drawable-mdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..db24457
--- /dev/null
+++ b/res/drawable-mdpi/widget_container_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_preview_tile.png b/res/drawable-mdpi/widget_preview_tile.png
new file mode 100644
index 0000000..9c7c4f7
--- /dev/null
+++ b/res/drawable-mdpi/widget_preview_tile.png
Binary files differ
diff --git a/res/drawable-nodpi/wallpaper_05.jpg b/res/drawable-nodpi/wallpaper_05.jpg
index d64d10a..e0b3770 100644
--- a/res/drawable-nodpi/wallpaper_05.jpg
+++ b/res/drawable-nodpi/wallpaper_05.jpg
Binary files differ
diff --git a/res/drawable-nodpi/wallpaper_05_small.jpg b/res/drawable-nodpi/wallpaper_05_small.jpg
index cd71bd3..2ae4a18 100644
--- a/res/drawable-nodpi/wallpaper_05_small.jpg
+++ b/res/drawable-nodpi/wallpaper_05_small.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_01.jpg b/res/drawable-sw600dp-nodpi/wallpaper_01.jpg
index 03a14c0..6dd81b9 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_01.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_01.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_02.jpg b/res/drawable-sw600dp-nodpi/wallpaper_02.jpg
index adab026..a363f0f 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_02.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_02.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_03.jpg b/res/drawable-sw600dp-nodpi/wallpaper_03.jpg
index f21de37..be8a8b7 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_03.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_03.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_04.jpg b/res/drawable-sw600dp-nodpi/wallpaper_04.jpg
index 1c366e7..0c9e72b 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_04.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_04.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_05.jpg b/res/drawable-sw600dp-nodpi/wallpaper_05.jpg
index 2c1284d..47013d3 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_05.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_05.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_08.jpg b/res/drawable-sw600dp-nodpi/wallpaper_08.jpg
index 2558382..2c3cbda 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_08.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_08.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_09.jpg b/res/drawable-sw600dp-nodpi/wallpaper_09.jpg
index e8d47ab..885ec35 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_09.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_09.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_10.jpg b/res/drawable-sw600dp-nodpi/wallpaper_10.jpg
index 7389534..695808f 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_10.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_10.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_11.jpg b/res/drawable-sw600dp-nodpi/wallpaper_11.jpg
index 3f3284e..94cc540 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_11.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_11.jpg
Binary files differ
diff --git a/res/drawable-sw600dp-nodpi/wallpaper_12.jpg b/res/drawable-sw600dp-nodpi/wallpaper_12.jpg
index 0891ea8..614498b 100644
--- a/res/drawable-sw600dp-nodpi/wallpaper_12.jpg
+++ b/res/drawable-sw600dp-nodpi/wallpaper_12.jpg
Binary files differ
diff --git a/res/drawable-xhdpi/widget_container_holo.9.png b/res/drawable-xhdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..1313fe7
--- /dev/null
+++ b/res/drawable-xhdpi/widget_container_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_preview_tile.png b/res/drawable-xhdpi/widget_preview_tile.png
new file mode 100644
index 0000000..6023867
--- /dev/null
+++ b/res/drawable-xhdpi/widget_preview_tile.png
Binary files differ
diff --git a/res/layout-land/apps_customize_application.xml b/res/layout-land/apps_customize_application.xml
index bface6b..ba95b27 100644
--- a/res/layout-land/apps_customize_application.xml
+++ b/res/layout-land/apps_customize_application.xml
@@ -25,8 +25,5 @@
     android:layout_height="match_parent"
     android:gravity="center_horizontal"
 
-    launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF"
-
     android:focusable="true"
     android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-land/drop_target_bar.xml b/res/layout-land/drop_target_bar.xml
index 55d9421..794a79e 100644
--- a/res/layout-land/drop_target_bar.xml
+++ b/res/layout-land/drop_target_bar.xml
@@ -22,7 +22,7 @@
         <com.android.launcher2.DeleteDropTarget
             style="@style/DropTargetButton"
             android:id="@+id/delete_target_text"
-            android:drawableTop="@drawable/info_target_selector" />
+            android:drawableTop="@drawable/remove_target_selector" />
     </FrameLayout>
     <FrameLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 99d4181..6b65f56 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -76,6 +76,16 @@
         android:id="@+id/qsb_bar"
         layout="@layout/qsb_bar" />
 
+    <com.android.launcher2.DrawableStateProxyView
+        android:id="@+id/voice_button_proxy"
+        android:layout_width="@dimen/qsb_bar_height"
+        android:layout_height="@dimen/app_icon_size"
+        android:layout_gravity="bottom|left"
+        android:clickable="true"
+        android:onClick="onClickVoiceButton"
+        android:importantForAccessibility="no"
+        launcher:sourceViewId="@+id/voice_button" />
+
     <include layout="@layout/apps_customize_pane"
         android:id="@+id/apps_customize_pane"
         android:layout_width="match_parent"
diff --git a/res/layout-port/apps_customize_application.xml b/res/layout-port/apps_customize_application.xml
index 37b4185..84a8712 100644
--- a/res/layout-port/apps_customize_application.xml
+++ b/res/layout-port/apps_customize_application.xml
@@ -25,8 +25,5 @@
     android:layout_height="match_parent"
     android:gravity="center_horizontal"
 
-    launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF"
-
     android:focusable="true"
     android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index f60a204..a427501 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -75,9 +75,9 @@
 
     <com.android.launcher2.DrawableStateProxyView
         android:id="@+id/voice_button_proxy"
-        android:layout_width="@dimen/qsb_bar_height"
+        android:layout_width="80dp"
         android:layout_height="@dimen/qsb_bar_height"
-        android:layout_gravity="right"
+        android:layout_gravity="top|right"
         android:clickable="true"
         android:onClick="onClickVoiceButton"
         android:importantForAccessibility="no"
diff --git a/res/layout-sw600dp-port/all_apps_cling.xml b/res/layout-sw600dp-port/all_apps_cling.xml
index 8bf8d15..95d7ff2 100644
--- a/res/layout-sw600dp-port/all_apps_cling.xml
+++ b/res/layout-sw600dp-port/all_apps_cling.xml
@@ -41,8 +41,6 @@
     <Button
         style="@style/ClingButton"
         android:id="@+id/cling_dismiss"
-        android:layout_width="118dp"
-        android:layout_height="54dp"
         android:textSize="24sp"
         android:layout_marginBottom="27dp"
         android:layout_marginRight="36dp"
diff --git a/res/layout-sw600dp-port/folder_cling.xml b/res/layout-sw600dp-port/folder_cling.xml
index d154a5b..1b6c1a0 100644
--- a/res/layout-sw600dp-port/folder_cling.xml
+++ b/res/layout-sw600dp-port/folder_cling.xml
@@ -42,8 +42,6 @@
     <Button
         style="@style/ClingButton"
         android:id="@+id/cling_dismiss"
-        android:layout_width="118dp"
-        android:layout_height="54dp"
         android:textSize="24sp"
         android:layout_marginBottom="27dp"
         android:layout_marginRight="36dp"
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
index 90883c5..abb7508 100644
--- a/res/layout/apps_customize_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -22,16 +22,27 @@
     android:layout_weight="1"
     android:orientation="vertical"
 
-    launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF"
-
     android:background="@drawable/focusable_view_bg"
     android:focusable="true">
 
+    <!-- The preview of the widget or shortcut. -->
+    <com.android.launcher2.PagedViewWidgetImageView
+        android:id="@+id/widget_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="@dimen/app_widget_preview_padding_top"
+        android:paddingLeft="@dimen/app_widget_preview_padding_left"
+        android:paddingRight="@dimen/app_widget_preview_padding_right"
+        android:scaleType="matrix"
+        android:background="@drawable/widget_container_holo" />
+
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="4dp"
+        android:layout_marginTop="@dimen/app_widget_preview_label_margin_top"
+        android:layout_marginLeft="@dimen/app_widget_preview_label_margin_left"
+        android:layout_marginRight="@dimen/app_widget_preview_label_margin_right"
         android:orientation="horizontal">
         <!-- The name of the widget. -->
         <TextView xmlns:android="http://schemas.android.com/apk/res/android"
@@ -62,13 +73,5 @@
             android:textSize="12sp" />
     </LinearLayout>
 
-    <!-- The icon of the widget. -->
-    <com.android.launcher2.PagedViewWidgetImageView
-        android:id="@+id/widget_preview"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:paddingTop="@dimen/app_widget_preview_padding_top"
-        android:paddingLeft="@dimen/app_widget_preview_padding_left"
-        android:scaleType="matrix" />
+
 </com.android.launcher2.PagedViewWidget>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 726505d..72ba855 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Vouer is gesluit"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Vouer hernoem na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 25cb8ca..2319638 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"አቃፊ ተዘግቷል"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"አቃፊ ዳግም ወደ <xliff:g id="NAME">%1$s</xliff:g> ተሰይሟል"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"አቃፊ ስም፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index bbe52b0..0ddd369 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"تم إغلاق المجلد"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"تمت إعادة تسمية المجلد إلى <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 98939d6..150434f 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Тэчка закрыта"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Тэчка перайменавана ў <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Тэчка <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index b444199..f435ff6 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Папката бе затворена"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Папката е преименувана на „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index a68109c..6ed84db 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Carpeta tancada"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"S\'ha canviat el nom de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 3ad9f9b..dea19f6 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -23,7 +23,7 @@
     <string name="home" msgid="5921706419368316758">"Plocha"</string>
     <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
     <string name="folder_name" msgid="8551881338202938211"></string>
-    <string name="chooser_wallpaper" msgid="6063168087625352235">"Vybrat tapetu z"</string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Vybrat tapetu:"</string>
     <string name="wallpaper_instructions" msgid="4215640646180727542">"Nastavit tapetu"</string>
     <string name="pick_wallpaper" msgid="5630222540525626723">"Tapety"</string>
     <string name="activity_not_found" msgid="217823393239365967">"Aplikace není nainstalována."</string>
@@ -95,7 +95,7 @@
     <string name="workspace_cling_title" msgid="738396473989890567">"Chovejte se jako doma"</string>
     <string name="workspace_cling_move_item" msgid="791013895761065070">"Sem můžete umístit své oblíbené aplikace."</string>
     <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Chcete-li zobrazit všechny aplikace, dotkněte se kruhu."</string>
-    <string name="all_apps_cling_title" msgid="2559734712581447107">"Vybrat několik aplikací"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Vyberte nějaké aplikace"</string>
     <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Chcete-li na plochu přidat aplikaci, dotkněte se jí a přidržte ji."</string>
     <string name="folder_cling_title" msgid="4308949882377840953">"Uspořádat aplikace pomocí složek"</string>
     <string name="folder_cling_move_item" msgid="270598675060435169">"Chcete-li aplikaci přesunout, dotkněte se jí a přidržte ji."</string>
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Složka je uzavřena"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Složka přejmenována na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Složka: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index f205b5d..af00d82 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mappen er lukket"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mappen er omdøbt til <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 05df014..b9d35c2 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Ordner wurde geschlossen"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Ordner umbenannt in <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 4ec10e3..78e153a 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Ο φάκελος έκλεισε"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Ο φάκελος μετονομάστηκε σε <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index a1b4b25..ceb215a 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Folder closed"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 9395425..bc6566d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Se cerró la carpeta."</string>
     <string name="folder_renamed" msgid="7951233572858053642">"El nombre de la carpeta se cambió a <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index fde69a2..2987f3e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Carpeta cerrada"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Se ha cambiado el nombre de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index e1d5c37..78c983a 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Kaust suletud"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Kausta uus nimi: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 32ba622..d03e82a 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"پوشه بسته شد"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"نام پوشه به <xliff:g id="NAME">%1$s</xliff:g> تغییر کرد"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d8cd3ea..29f3826 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Kansio on suljettu"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Kansion nimeksi vaihdettiin <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 79d10c2..43bf837 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Dossier fermé"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 162d3a9..c5ae89a 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"फ़ोल्डर बंद किया गया"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 56bab83..665d7b3 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mapa zatvorena"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mapa je preimenovana u <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 4c59941..761ee72 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mappa lezárva"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mappa új neve: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 77bca53..3ba6225 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Folder ditutup"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Folder diubah namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 2635367..9a73872 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Cartella chiusa"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Cartella rinominata in <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 4962a23..8dd6cd9 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"התיקייה נסגרה"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"שם התיקיה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"תיקיה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ef7ee83..7e29730 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"フォルダは閉じています"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"フォルダの名前を「<xliff:g id="NAME">%1$s</xliff:g>」に変更しました"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 0e42cdd..990dcfb 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"폴더 닫음"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"폴더 이름 변경: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"폴더: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index c1d70d9..885ecf0 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Aplankas uždarytas"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Aplankas pervardytas kaip „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Aplankas: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index d100dc5..c1cd545 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mape aizvērta"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mape pārdēvēta par: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mape: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 1c9a0dc..3f2d0d8 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Folder ditutup"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Folder dinamakan semula kepada <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index d1f2ce6..a345516 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mappen ble lukket"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mappen heter nå <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 7922d3e..457ac30 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Map gesloten"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"De naam van de map is gewijzigd in <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 64972ba..20b4217 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -23,7 +23,7 @@
     <string name="home" msgid="5921706419368316758">"Strona główna"</string>
     <string name="uid_name" msgid="3371120195364560632">"Aplikacje główne systemu Android"</string>
     <string name="folder_name" msgid="8551881338202938211"></string>
-    <string name="chooser_wallpaper" msgid="6063168087625352235">"Wybierz tapetę z"</string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Wybierz tapetę z..."</string>
     <string name="wallpaper_instructions" msgid="4215640646180727542">"Ustaw tapetę"</string>
     <string name="pick_wallpaper" msgid="5630222540525626723">"Tapety"</string>
     <string name="activity_not_found" msgid="217823393239365967">"Aplikacja nie jest zainstalowana."</string>
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Folder zamknięty"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Nazwa folderu zmieniona na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index de5309f..d7cedc0 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Pasta fechada"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Nome de pasta alterado para <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 4ff36e0..53468bf 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Pasta fechada"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Pasta renomeada para <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 36ff983..99f72bb 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -168,4 +168,8 @@
     <skip />
     <!-- no translation found for folder_name_format (3051680259794759037) -->
     <skip />
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index f02c16a..1ed96ac 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Dosar închis"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Dosar redenumit <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 4f28f4e..19d2152 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Папка закрыта"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Папка переименована в \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 06c18f2..43c4c16 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Priečinok je uzavretý"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Priečinok bol premenovaný na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 50ea28f..3217c0a 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mapa je zaprta"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mapa je preimenovana v <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 541e34c..5dd726a 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Директоријум је затворен"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Директоријум је преименован у <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Директоријум: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 822e3b3..067b5f1 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Mappen är stängd"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Mappen har bytt namn till <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 95a3a10..676edcb 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -109,4 +109,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Folda imefungwa"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Folda imebadilishwa jina hadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 9c54cf3..1093729 100644
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -31,4 +31,10 @@
 
 <!-- QSB -->
     <dimen name="qsb_bar_height">82dp</dimen>
+
+<!-- Workspace -->
+    <dimen name="workspace_divider_padding_top">12dp</dimen>
+    <dimen name="workspace_divider_padding_bottom">12dp</dimen>
+    <dimen name="workspace_divider_padding_left">0dp</dimen>
+    <dimen name="workspace_divider_padding_right">0dp</dimen>
 </resources>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index a701e69..a463d73 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -4,6 +4,9 @@
     <integer name="hotseat_cell_count">7</integer>
     <integer name="hotseat_all_apps_index">3</integer>
 
+<!-- DragController -->
+    <integer name="config_flingToDeleteMinVelocity">-1000</integer>
+
 <!-- Folders -->
     <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y
         >= folder_max_num_items. When these are set to -1, they are automatically determined. -->
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 99e8909..bb6cbc9 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -61,7 +61,9 @@
     <dimen name="apps_customize_tab_bar_margin_top">8dp</dimen>
     <dimen name="apps_customize_widget_cell_width_gap">20dp</dimen>
     <dimen name="apps_customize_widget_cell_height_gap">24dp</dimen>
-
+    <dimen name="app_widget_preview_label_margin_top">8dp</dimen>
+    <dimen name="app_widget_preview_label_margin_left">@dimen/app_widget_preview_padding_left</dimen>
+    <dimen name="app_widget_preview_label_margin_right">@dimen/app_widget_preview_padding_right</dimen>
 <!-- Workspace cell size -->
     <dimen name="workspace_cell_width_land">88dp</dimen>
     <dimen name="workspace_cell_width_port">96dp</dimen>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index cfd76dc..7daccd0 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -40,9 +40,6 @@
     <dimen name="apps_customize_cell_height">96dp</dimen>
     <integer name="apps_customize_maxCellCountX">-1</integer>
     <integer name="apps_customize_maxCellCountY">-1</integer>
-    <dimen name="app_widget_preview_padding_left">0dp</dimen>
-    <dimen name="app_widget_preview_padding_top">10dp</dimen>
-
     <dimen name="all_apps_button_vertical_padding">4dip</dimen>
 
     <!-- roughly a status bar (for determining how many rows of icons are in home) -->
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 26ad7dc..91070ad 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"โฟลเดอร์ปิดอยู่"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"เปลี่ยนชื่อโฟลเดอร์เป็น <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 878fca6..dfa5357 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Nakasara ang folder"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Binago ang pangalan ng folder patungong <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 47b6d1a..d9ce915 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Klasör kapatıldı"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Klasörün adı <xliff:g id="NAME">%1$s</xliff:g> olarak değiştirildi"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 34204e9..5031ea9 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Папку закрито"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Папку перейменовано на <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index bd84e54..232aa0a 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Đã đóng thư mục"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Đã đổi tên thư mục thành <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 4d73486..f5eeab1 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -87,12 +87,12 @@
     <string name="uninstall_system_app_text" msgid="6429814133777046491">"这是系统应用,无法卸载。"</string>
     <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="8633351560105748141">"未命名文件夹"</string>
-    <string name="workspace_description_format" msgid="2968608205939373034">"主屏幕第 %1$d 页"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"主屏幕 %1$d"</string>
     <string name="default_scroll_format" msgid="4057140866420001240">"第 %1$d 页,共 %2$d 页"</string>
-    <string name="workspace_scroll_format" msgid="1704767047951143301">"主屏幕第 %1$d 页,共 %2$d 页"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"主屏幕 %1$d(共 %2$d 个)"</string>
     <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"应用:第 %1$d 页,共 %2$d 页"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"窗口小部件:第 %1$d 页,共 %2$d 页"</string>
-    <string name="workspace_cling_title" msgid="738396473989890567">"随意浏览"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"您的主屏幕您做主"</string>
     <string name="workspace_cling_move_item" msgid="791013895761065070">"您可以在此处放置自己喜爱的应用。"</string>
     <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"要查看您的所有应用,请触摸该圆圈。"</string>
     <string name="all_apps_cling_title" msgid="2559734712581447107">"选择一些应用"</string>
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"文件夹已关闭"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"已将文件夹重命名为“<xliff:g id="NAME">%1$s</xliff:g>”"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 9e5de78..f261ddf 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"已關閉資料夾"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"已將資料夾重新命名為 <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 7b3c6a5..6faa63d 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -107,4 +107,8 @@
     <string name="folder_closed" msgid="3130534551370511932">"Ifolda ivaliwe"</string>
     <string name="folder_renamed" msgid="7951233572858053642">"Ifolda iqanjwe kabusha ngo-<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="3051680259794759037">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index cd939db..c76a6a5 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -93,24 +93,6 @@
         <attr name="sourceImageViewId" format="integer" />
     </declare-styleable>
 
-    <!-- PagedViewIcon specific attributes. These attributes are used to customize
-         a PagedViewIcon view in XML files. -->
-    <declare-styleable name="PagedViewIcon">
-        <!-- The blur color of the holographic outline -->
-        <attr name="blurColor" format="color" />
-        <!-- The outline color of the holographic outline -->
-        <attr name="outlineColor" format="color" />
-    </declare-styleable>
-
-    <!-- PagedViewWidget specific attributes. These attributes are used to
-         customize a PagedViewWidget view in XML files. -->
-    <declare-styleable name="PagedViewWidget">
-        <!-- The blur color of the holographic outline -->
-        <attr name="blurColor" />
-        <!-- The outline color of the holographic outline -->
-        <attr name="outlineColor" />
-    </declare-styleable>
-
     <!-- PagedView specific attributes. These attributes are used to customize
          a PagedView view in XML files. -->
     <declare-styleable name="PagedView">
@@ -175,4 +157,10 @@
         <attr name="key" format="string" />
         <attr name="value" format="string" />
     </declare-styleable>
+
+    <!-- Only used in the device overlays -->
+    <declare-styleable name="CustomClingTitleText">
+    </declare-styleable>
+    <declare-styleable name="CustomClingText">
+    </declare-styleable>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index bfd2bf5..a8d80fe 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -4,6 +4,9 @@
     <bool name="is_large_screen">false</bool>
     <bool name="allow_rotation">false</bool>
 
+<!-- DragController -->
+    <integer name="config_flingToDeleteMinVelocity">-1500</integer>
+
 <!-- AllApps/Customize/AppsCustomize -->
     <!-- The alpha of the AppsCustomize bg in spring loaded mode -->
     <integer name="config_appsCustomizeSpringLoadedBgAlpha">45</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e789fdf..7cc8960 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -105,9 +105,18 @@
           should be. If 0, it will not be scaled at all. -->
     <dimen name="dragViewScale">12dp</dimen>
 
-    <!-- Padding applied to AppWidgets -->
-    <dimen name="app_widget_preview_padding_left">8dp</dimen>
-    <dimen name="app_widget_preview_padding_top">8dp</dimen>
+    <!-- Padding applied to AppWidget previews -->
+    <dimen name="app_widget_preview_padding_left">16dp</dimen>
+    <dimen name="app_widget_preview_padding_right">16dp</dimen>
+    <dimen name="app_widget_preview_padding_top">32dp</dimen>
+    <dimen name="app_widget_preview_label_margin_top">4dp</dimen>
+    <dimen name="app_widget_preview_label_margin_left">2dp</dimen>
+    <dimen name="app_widget_preview_label_margin_right">2dp</dimen>
+
+    <!-- Padding applied to shortcut previews -->
+    <dimen name="shortcut_preview_padding_left">0dp</dimen>
+    <dimen name="shortcut_preview_padding_right">0dp</dimen>
+    <dimen name="shortcut_preview_padding_top">0dp</dimen>
 
 <!-- Folders -->
     <!-- The size of the image which sits behind the preview of the folder contents -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1416d40..4aee339 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -260,4 +260,16 @@
     <!-- Folder name format -->
     <string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
 
+    <!-- Strings used in device overlays -->
+
+    <!-- Clings -->
+    <!-- Dummy string [CHAR_LIMIT=40] -->
+    <string name="custom_workspace_cling_title_1"></string>
+    <!-- Dummy string [CHAR_LIMIT=60] -->
+    <string name="custom_workspace_cling_description_1"></string>
+    <!-- Dummy string [CHAR_LIMIT=40] -->
+    <string name="custom_workspace_cling_title_2"></string>
+    <!-- Dummy string [CHAR_LIMIT=60] -->
+    <string name="custom_workspace_cling_description_2"></string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3d935a1..08c98c9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -186,4 +186,10 @@
         <item name="android:shadowDy">0.0</item>
         <item name="android:shadowRadius">2.0</item>
     </style>
+
+    <!-- Overridden in device overlays -->
+    <style name="CustomClingTitleText">
+    </style>
+    <style name="CustomClingText">
+    </style>
 </resources>
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 5e0d43d..45bb08a 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -33,12 +33,18 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Insets;
 import android.graphics.MaskFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Shader;
 import android.graphics.TableMaskFilter;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Process;
@@ -54,6 +60,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.widget.GridLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.Toast;
 
 import com.android.launcher.R;
@@ -63,6 +70,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.lang.ref.WeakReference;
 
 /**
  * A simple callback interface which also provides the results of the task.
@@ -163,6 +171,64 @@
     int threadPriority;
 }
 
+abstract class WeakReferenceThreadLocal<T> {
+    private ThreadLocal<WeakReference<T>> mThreadLocal;
+    public WeakReferenceThreadLocal() {
+        mThreadLocal = new ThreadLocal<WeakReference<T>>();
+    }
+
+    abstract T initialValue();
+
+    public void set(T t) {
+        mThreadLocal.set(new WeakReference<T>(t));
+    }
+
+    public T get() {
+        WeakReference<T> reference = mThreadLocal.get();
+        T obj;
+        if (reference == null) {
+            obj = initialValue();
+            mThreadLocal.set(new WeakReference<T>(obj));
+            return obj;
+        } else {
+            obj = reference.get();
+            if (obj == null) {
+                obj = initialValue();
+                mThreadLocal.set(new WeakReference<T>(obj));
+            }
+            return obj;
+        }
+    }
+}
+
+class CanvasCache extends WeakReferenceThreadLocal<Canvas> {
+    @Override
+    protected Canvas initialValue() {
+        return new Canvas();
+    }
+}
+
+class PaintCache extends WeakReferenceThreadLocal<Paint> {
+    @Override
+    protected Paint initialValue() {
+        return null;
+    }
+}
+
+class BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
+    @Override
+    protected Bitmap initialValue() {
+        return null;
+    }
+}
+
+class RectCache extends WeakReferenceThreadLocal<Rect> {
+    @Override
+    protected Rect initialValue() {
+        return new Rect();
+    }
+}
+
 /**
  * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
  */
@@ -210,7 +276,6 @@
     private int mMaxAppCellCountX, mMaxAppCellCountY;
     private int mWidgetCountX, mWidgetCountY;
     private int mWidgetWidthGap, mWidgetHeightGap;
-    private final int mWidgetPreviewIconPaddedDimension;
     private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
     private PagedViewCellLayout mWidgetSpacingLayout;
     private int mNumAppsPages;
@@ -233,8 +298,9 @@
     private Runnable mInflateWidgetRunnable = null;
     private Runnable mBindWidgetRunnable = null;
     static final int WIDGET_NO_CLEANUP_REQUIRED = -1;
-    static final int WIDGET_BOUND = 0;
-    static final int WIDGET_INFLATED = 1;
+    static final int WIDGET_PRELOAD_PENDING = 0;
+    static final int WIDGET_BOUND = 1;
+    static final int WIDGET_INFLATED = 2;
     int mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
     int mWidgetLoadingId = -1;
     PendingAddWidgetInfo mCreateWidgetInfo = null;
@@ -245,6 +311,17 @@
     private ArrayList<AsyncTaskPageData> mDeferredSyncWidgetPageItems =
         new ArrayList<AsyncTaskPageData>();
 
+    // Used for drawing shortcut previews
+    BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
+    PaintCache mCachedShortcutPreviewPaint = new PaintCache();
+    CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
+
+    // Used for drawing widget previews
+    CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
+    RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
+    RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
+    PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
+
     public AppsCustomizePagedView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mLayoutInflater = LayoutInflater.from(context);
@@ -276,14 +353,14 @@
 
         // The padding on the non-matched dimension for the default widget preview icons
         // (top + bottom)
-        mWidgetPreviewIconPaddedDimension =
-            (int) (mAppIconSize * (1 + (2 * sWidgetPreviewIconPaddingPercentage)));
         mFadeInAdjacentScreens = false;
 
         // Unless otherwise specified this view is important for accessibility.
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+
+        Log.d(TAG, "6549598 ctor mNumWidgetPages: " + mNumWidgetPages + " mNumAppsPages: " + mNumAppsPages);
     }
 
     @Override
@@ -294,6 +371,7 @@
         Context context = getContext();
         Resources r = context.getResources();
         setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+        Log.d(TAG, "6549598 init mNumWidgetPages: " + mNumWidgetPages + " mNumAppsPages: " + mNumAppsPages);
     }
 
     @Override
@@ -374,9 +452,12 @@
         mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
                 (float) (mWidgetCountX * mWidgetCountY));
         mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+        Log.d(TAG, "6549598 updatePageCounts mNumWidgetPages: " + mNumWidgetPages + " mNumAppsPages: " + mNumAppsPages);
+        Log.d(TAG, "6549598 mApps.size(): " + mApps.size() + " mWidgets.size(): " + mWidgets.size() + " mCellCountX: " + mCellCountX + " mCellCountY: " + mCellCountY);
     }
 
     protected void onDataReady(int width, int height) {
+        Log.d(TAG, "6549598 onDataReady");
         // Note that we transpose the counts in portrait so that we get a similar layout
         boolean isLandscape = getResources().getConfiguration().orientation ==
             Configuration.ORIENTATION_LANDSCAPE;
@@ -462,16 +543,18 @@
     }
 
     public void onPackagesUpdated() {
+        Log.d(TAG, "6549598 onPackagesUpdated");
         // TODO: this isn't ideal, but we actually need to delay here. This call is triggered
         // by a broadcast receiver, and in order for it to work correctly, we need to know that
         // the AppWidgetService has already received and processed the same broadcast. Since there
-        // is no guarantee about ordering of broadcast receipt, we just delay here. Ideally,
-        // we should have a more precise way of ensuring the AppWidgetService is up to date.
+        // is no guarantee about ordering of broadcast receipt, we just delay here. This is a
+        // workaround until we add a callback from AppWidgetService to AppWidgetHost when widget
+        // packages are added, updated or removed.
         postDelayed(new Runnable() {
            public void run() {
                updatePackages();
            }
-        }, 500);
+        }, 1500);
     }
 
     public void updatePackages() {
@@ -492,6 +575,9 @@
                 if (minSpanX <= LauncherModel.getCellCountX() &&
                         minSpanY <= LauncherModel.getCellCountY()) {
                     mWidgets.add(widget);
+                } else {
+                    Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
+                            widget.minWidth + ", " + widget.minHeight + ")");
                 }
             } else {
                 Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
@@ -501,6 +587,7 @@
         mWidgets.addAll(shortcuts);
         Collections.sort(mWidgets,
                 new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
+        Log.d(TAG, "6549598 updatePackages mWidgets.size(): " + mWidgets.size() + " wasEmpty: " + wasEmpty);
         updatePageCounts();
 
         if (wasEmpty) {
@@ -571,14 +658,17 @@
     }
 
     private void preloadWidget(final PendingAddWidgetInfo info) {
+        Log.d(TAG, "6557954 Preload widget: " + info.info);
         final AppWidgetProviderInfo pInfo = info.info;
         if (pInfo.configure != null) {
             return;
         }
 
+        mWidgetCleanupState = WIDGET_PRELOAD_PENDING;
         mBindWidgetRunnable = new Runnable() {
             @Override
             public void run() {
+                Log.d(TAG, "    6557954 Preload, bind widget: " + info.info);
                 mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
                 if (AppWidgetManager.getInstance(mLauncher)
                             .bindAppWidgetIdIfAllowed(mWidgetLoadingId, info.componentName)) {
@@ -594,6 +684,7 @@
                 AppWidgetHostView hostView = mLauncher.
                         getAppWidgetHost().createView(getContext(), mWidgetLoadingId, pInfo);
                 info.boundWidget = hostView;
+                Log.d(TAG, "    6557954 Preload, inflate widget: " + info.info);
                 mWidgetCleanupState = WIDGET_INFLATED;
                 hostView.setVisibility(INVISIBLE);
                 int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info.spanX,
@@ -618,27 +709,49 @@
         // the widget. This will need to be cleaned up if it turns out no long press occurs.
         if (mCreateWidgetInfo != null) {
             // Just in case the cleanup process wasn't properly executed. This shouldn't happen.
+            Log.d(TAG, "**** 6557954 Previous shortpress not cleaned up, cleaning up now: " + mCreateWidgetInfo.info);
             cleanupWidgetPreloading(false);
         }
         mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag());
+        Log.d(TAG, "6557954 Short press triggered for view: " + v + ", widget info: " + mCreateWidgetInfo.info);
         preloadWidget(mCreateWidgetInfo);
     }
 
     private void cleanupWidgetPreloading(boolean widgetWasAdded) {
+        Log.d(TAG, "6557954 Cleaning up widget, was added: " + widgetWasAdded);
+        if (mCreateWidgetInfo != null) {
+            Log.d(TAG, "    6557954 Cleaning up widget, widget info: " + mCreateWidgetInfo.info);
+        }
+
         if (!widgetWasAdded) {
             // If the widget was not added, we may need to do further cleanup.
             PendingAddWidgetInfo info = mCreateWidgetInfo;
             mCreateWidgetInfo = null;
-            // First step was to allocate a widget id, revert that.
-            if ((mWidgetCleanupState == WIDGET_BOUND || mWidgetCleanupState == WIDGET_INFLATED) &&
-                    mWidgetLoadingId != -1) {
-                mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
-            }
-            if (mWidgetCleanupState == WIDGET_BOUND) {
-                // We never actually inflated the widget, so remove the callback to do so.
+
+            if (mWidgetCleanupState == WIDGET_PRELOAD_PENDING) {
+                Log.d(TAG, "    6557954 Cleaning up widget, remove preload callbacks");
+                // We never did any preloading, so just remove pending callbacks to do so
+                removeCallbacks(mBindWidgetRunnable);
+                removeCallbacks(mInflateWidgetRunnable);
+            } else if (mWidgetCleanupState == WIDGET_BOUND) {
+                 // Delete the widget id which was allocated
+                if (mWidgetLoadingId != -1) {
+                    Log.d(TAG, "    6557954 Cleaning up widget, delete widget id");
+                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+                }
+
+                // We never got around to inflating the widget, so remove the callback to do so.
+                Log.d(TAG, "    6557954 Cleaning up widget, remove callbacks");
                 removeCallbacks(mInflateWidgetRunnable);
             } else if (mWidgetCleanupState == WIDGET_INFLATED) {
+                // Delete the widget id which was allocated
+                if (mWidgetLoadingId != -1) {
+                    Log.d(TAG, "    6557954 Cleaning up widget, delete widget id");
+                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+                }
+
                 // The widget was inflated and added to the DragLayer -- remove it.
+                Log.d(TAG, "    6557954 Cleaning up widget, remove inflated widget from draglayer");
                 AppWidgetHostView widget = info.boundWidget;
                 mLauncher.getDragLayer().removeView(widget);
             }
@@ -651,7 +764,9 @@
 
     @Override
     public void cleanUpShortPress(View v) {
+        Log.d(TAG, "6557954 Cleanup shortpress");
         if (!mDraggingWidget) {
+            Log.d(TAG, "    6557954 Cleanup shortpress, cleanup cleanup preloading");
             cleanupWidgetPreloading(false);
         }
     }
@@ -662,9 +777,15 @@
         ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
         PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
 
+        if (createItemInfo instanceof PendingAddWidgetInfo) {
+            PendingAddWidgetInfo createWidgetInfo = mCreateWidgetInfo;
+            Log.d(TAG, "6557954 Begin dragging widget, view: " + v + ", widget info: " + createWidgetInfo.info);
+        }
+
         // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
         // we abort the drag.
         if (image.getDrawable() == null) {
+            Log.d(TAG, "    6557954 Begin dragging widget, abort, no drawable set");
             mDraggingWidget = false;
             return false;
         }
@@ -689,11 +810,11 @@
 
             FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
             float minScale = 1.25f;
-            int minWidth, minHeight;
-            minWidth = Math.max((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
-            minHeight = Math.max((int) (previewDrawable.getIntrinsicHeight() * minScale), size[1]);
+            int maxWidth, maxHeight;
+            maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
+            maxHeight = Math.min((int) (previewDrawable.getIntrinsicHeight() * minScale), size[1]);
             preview = getWidgetPreview(createWidgetInfo.componentName, createWidgetInfo.previewImage,
-                    createWidgetInfo.icon, spanX, spanY, minWidth, minHeight);
+                    createWidgetInfo.icon, spanX, spanY, maxWidth, maxHeight);
 
             // Determine the image view drawable scale relative to the preview
             float[] mv = new float[9];
@@ -706,17 +827,15 @@
             m.getValues(mv);
             scale = (float) mv[0];
         } else {
-            // Workaround for the fact that we don't keep the original ResolveInfo associated with
-            // the shortcut around.  To get the icon, we just render the preview image (which has
-            // the shortcut icon) to a new drag bitmap that clips the non-icon space.
-            preview = Bitmap.createBitmap(mWidgetPreviewIconPaddedDimension,
-                    mWidgetPreviewIconPaddedDimension, Bitmap.Config.ARGB_8888);
-            Drawable d = image.getDrawable();
+            PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
+            Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
+            preview = Bitmap.createBitmap(icon.getIntrinsicWidth(),
+                    icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
             mCanvas.setBitmap(preview);
             mCanvas.save();
-            mCanvas.translate((mWidgetPreviewIconPaddedDimension - d.getIntrinsicWidth()) / 2,
-                    (mWidgetPreviewIconPaddedDimension - d.getIntrinsicHeight()) / 2);
-            d.draw(mCanvas);
+            renderDrawableToBitmap(icon, preview, 0, 0,
+                    icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
             mCanvas.restore();
             mCanvas.setBitmap(null);
             createItemInfo.spanX = createItemInfo.spanY = 1;
@@ -819,6 +938,7 @@
 
     @Override
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+        Log.d(TAG, "6549598 onLauncherTransitionEnd");
         mInTransition = false;
         for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
             onSyncWidgetPageItems(d);
@@ -899,11 +1019,18 @@
             task.cancel(false);
             iter.remove();
             mDirtyPageContent.set(task.page, true);
+
+            // We've already preallocated the views for the data to load into, so clear them as well
+            View v = getPageAt(task.page);
+            if (v instanceof PagedViewGridLayout) {
+                ((PagedViewGridLayout) v).removeAllViewsOnPage();
+            }
         }
         mDeferredSyncWidgetPageItems.clear();
     }
 
     public void setContentType(ContentType type) {
+        Log.d(TAG, "6549598 setContentType mNumAppsPages: " + mNumAppsPages);
         if (type == ContentType.Widgets) {
             invalidatePageData(mNumAppsPages, true);
         } else if (type == ContentType.Applications) {
@@ -930,6 +1057,7 @@
     }
 
     private void updateCurrentTab(int currentPage) {
+        Log.d(TAG, "6549598 updateCurrentTab mNumAppsPages: " + mNumAppsPages);
         AppsCustomizeTabHost tabHost = getTabHost();
         if (tabHost != null) {
             String tag = tabHost.getCurrentTabTag();
@@ -973,6 +1101,7 @@
     }
 
     public void syncAppsPageItems(int page, boolean immediate) {
+        Log.d(TAG, "6549598 syncAppsPageItems page: " + page);
         // ensure that we have the right number of items on the pages
         int numCells = mCellCountX * mCellCountY;
         int startIndex = page * numCells;
@@ -1118,11 +1247,11 @@
     }
 
     private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
-        renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f, 0xFFFFFFFF);
+        renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
     }
 
     private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
-            float scale, int multiplyColor) {
+            float scale) {
         if (bitmap != null) {
             Canvas c = new Canvas(bitmap);
             c.scale(scale, scale);
@@ -1133,20 +1262,60 @@
             c.setBitmap(null);
         }
     }
-    private Bitmap getShortcutPreview(ResolveInfo info) {
-        // Render the background
-        int offset = 0;
-        int bitmapSize = mAppIconSize;
-        Bitmap preview = Bitmap.createBitmap(bitmapSize, bitmapSize, Config.ARGB_8888);
 
+    private Bitmap getShortcutPreview(ResolveInfo info, int maxWidth, int maxHeight) {
+        Bitmap tempBitmap = mCachedShortcutPreviewBitmap.get();
+        final Canvas c = mCachedShortcutPreviewCanvas.get();
+        if (tempBitmap == null ||
+                tempBitmap.getWidth() != maxWidth ||
+                tempBitmap.getHeight() != maxHeight) {
+            tempBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+            mCachedShortcutPreviewBitmap.set(tempBitmap);
+        } else {
+            c.setBitmap(tempBitmap);
+            c.drawColor(0, PorterDuff.Mode.CLEAR);
+            c.setBitmap(null);
+        }
         // Render the icon
         Drawable icon = mIconCache.getFullResIcon(info);
-        renderDrawableToBitmap(icon, preview, offset, offset, mAppIconSize, mAppIconSize);
+
+        int paddingTop =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
+        int paddingLeft =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
+        int paddingRight =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
+
+        int scaledIconWidth = (maxWidth - paddingLeft - paddingRight);
+        float scaleSize = scaledIconWidth / (float) mAppIconSize;
+
+        renderDrawableToBitmap(
+                icon, tempBitmap, paddingLeft, paddingTop, scaledIconWidth, scaledIconWidth);
+
+        Bitmap preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+        c.setBitmap(preview);
+        Paint p = mCachedShortcutPreviewPaint.get();
+        if (p == null) {
+            p = new Paint();
+            ColorMatrix colorMatrix = new ColorMatrix();
+            colorMatrix.setSaturation(0);
+            p.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
+            p.setAlpha((int) (255 * 0.06f));
+            //float density = 1f;
+            //p.setMaskFilter(new BlurMaskFilter(15*density, BlurMaskFilter.Blur.NORMAL));
+            mCachedShortcutPreviewPaint.set(p);
+        }
+        c.drawBitmap(tempBitmap, 0, 0, p);
+        c.setBitmap(null);
+
+        renderDrawableToBitmap(icon, preview, 0, 0, mAppIconSize, mAppIconSize);
+
         return preview;
     }
 
-    private Bitmap getWidgetPreview(ComponentName provider, int previewImage, int iconId,
-            int cellHSpan, int cellVSpan, int maxWidth, int maxHeight) {
+    private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
+            int iconId, int cellHSpan, int cellVSpan, int maxWidth,
+            int maxHeight) {
         // Load the preview image if possible
         String packageName = provider.getPackageName();
         if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
@@ -1163,73 +1332,99 @@
 
         int bitmapWidth;
         int bitmapHeight;
+        Bitmap defaultPreview = null;
         boolean widgetPreviewExists = (drawable != null);
         if (widgetPreviewExists) {
             bitmapWidth = drawable.getIntrinsicWidth();
             bitmapHeight = drawable.getIntrinsicHeight();
         } else {
+            // Generate a preview image if we couldn't load one
             if (cellHSpan < 1) cellHSpan = 1;
             if (cellVSpan < 1) cellVSpan = 1;
-            // Determine the size of the bitmap for the preview image we will generate
-            // TODO: This actually uses the apps customize cell layout params, where as we make want
-            // the Workspace params for more accuracy.
-            bitmapWidth = mWidgetSpacingLayout.estimateCellWidth(cellHSpan);
-            bitmapHeight = mWidgetSpacingLayout.estimateCellHeight(cellVSpan);
-            if (cellHSpan == cellVSpan) {
-                // For square widgets, we just have a fixed size for 1x1 and larger-than-1x1
-                int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
-                if (cellHSpan <= 1) {
-                    bitmapWidth = bitmapHeight = mAppIconSize + 2 * minOffset;
-                } else {
-                    bitmapWidth = bitmapHeight = mAppIconSize + 4 * minOffset;
+
+            BitmapDrawable previewDrawable = (BitmapDrawable) getResources()
+                    .getDrawable(R.drawable.widget_preview_tile);
+            final int previewDrawableWidth = previewDrawable
+                    .getIntrinsicWidth();
+            final int previewDrawableHeight = previewDrawable
+                    .getIntrinsicHeight();
+            bitmapWidth = previewDrawableWidth * cellHSpan; // subtract 2 dips
+            bitmapHeight = previewDrawableHeight * cellVSpan;
+
+            defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+                    Config.ARGB_8888);
+            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
+            c.setBitmap(defaultPreview);
+            previewDrawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
+            previewDrawable.setTileModeXY(Shader.TileMode.REPEAT,
+                    Shader.TileMode.REPEAT);
+            previewDrawable.draw(c);
+            c.setBitmap(null);
+
+            // Draw the icon in the top left corner
+            int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
+            int smallestSide = Math.min(bitmapWidth, bitmapHeight);
+            float iconScale = Math.min((float) smallestSide
+                    / (mAppIconSize + 2 * minOffset), 1f);
+
+            try {
+                Drawable icon = null;
+                int hoffset =
+                        (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
+                int yoffset =
+                        (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
+                if (iconId > 0)
+                    icon = mIconCache.getFullResIcon(packageName, iconId);
+                Resources resources = mLauncher.getResources();
+                if (icon != null) {
+                    renderDrawableToBitmap(icon, defaultPreview, hoffset,
+                            yoffset, (int) (mAppIconSize * iconScale),
+                            (int) (mAppIconSize * iconScale));
                 }
+            } catch (Resources.NotFoundException e) {
             }
         }
 
+        // Scale to fit width only - let the widget preview be clipped in the
+        // vertical dimension
         float scale = 1f;
         if (bitmapWidth > maxWidth) {
             scale = maxWidth / (float) bitmapWidth;
         }
-        if (bitmapHeight * scale > maxHeight) {
-            scale = maxHeight / (float) bitmapHeight;
-        }
         if (scale != 1f) {
             bitmapWidth = (int) (scale * bitmapWidth);
             bitmapHeight = (int) (scale * bitmapHeight);
         }
 
-        Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Config.ARGB_8888);
+        Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+                Config.ARGB_8888);
 
+        // Draw the scaled preview into the final bitmap
         if (widgetPreviewExists) {
-            renderDrawableToBitmap(drawable, preview, 0, 0, bitmapWidth, bitmapHeight);
+            renderDrawableToBitmap(drawable, preview, 0, 0, bitmapWidth,
+                    bitmapHeight);
         } else {
-            // Generate a preview image if we couldn't load one
-            int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
-            int smallestSide = Math.min(bitmapWidth, bitmapHeight);
-            float iconScale = Math.min((float) smallestSide / (mAppIconSize + 2 * minOffset), 1f);
-            if (cellHSpan != 1 || cellVSpan != 1) {
-                renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0, bitmapWidth,
-                        bitmapHeight);
+            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
+            final Rect src = mCachedAppWidgetPreviewSrcRect.get();
+            final Rect dest = mCachedAppWidgetPreviewDestRect.get();
+            c.setBitmap(preview);
+            src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
+            dest.set(0, 0, preview.getWidth(), preview.getHeight());
+
+            Paint p = mCachedAppWidgetPreviewPaint.get();
+            if (p == null) {
+                p = new Paint();
+                p.setFilterBitmap(true);
+                mCachedAppWidgetPreviewPaint.set(p);
             }
-
-            // Draw the icon in the top left corner
-            try {
-                Drawable icon = null;
-                int hoffset = (int) (bitmapWidth / 2 - mAppIconSize * iconScale / 2);
-                int yoffset = (int) (bitmapHeight / 2 - mAppIconSize * iconScale / 2);
-                if (iconId > 0) icon = mIconCache.getFullResIcon(packageName, iconId);
-                Resources resources = mLauncher.getResources();
-                if (icon == null) icon = resources.getDrawable(R.drawable.ic_launcher_application);
-
-                renderDrawableToBitmap(icon, preview, hoffset, yoffset,
-                        (int) (mAppIconSize * iconScale),
-                        (int) (mAppIconSize * iconScale));
-            } catch (Resources.NotFoundException e) {}
+            c.drawBitmap(defaultPreview, src, dest, p);
+            c.setBitmap(null);
         }
         return preview;
     }
 
     public void syncWidgetPageItems(final int page, final boolean immediate) {
+        Log.d(TAG, "6549598 syncWidgetPageItems page: " + page);
         int numItemsPerPage = mWidgetCountX * mWidgetCountY;
 
         // Calculate the dimensions of each cell we are giving to each widget
@@ -1274,7 +1469,7 @@
             } else if (rawInfo instanceof ResolveInfo) {
                 // Fill in the shortcuts information
                 ResolveInfo info = (ResolveInfo) rawInfo;
-                createItemInfo = new PendingAddItemInfo();
+                createItemInfo = new PendingAddShortcutInfo(info.activityInfo);
                 createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
                 createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
                         info.activityInfo.name);
@@ -1363,7 +1558,7 @@
             } else if (rawInfo instanceof ResolveInfo) {
                 // Fill in the shortcuts information
                 ResolveInfo info = (ResolveInfo) rawInfo;
-                images.add(getShortcutPreview(info));
+                images.add(getShortcutPreview(info, data.maxImageWidth, data.maxImageHeight));
             }
         }
     }
@@ -1421,10 +1616,13 @@
             setupPage(layout);
             addView(layout);
         }
+
+        Log.d(TAG, "6549598 syncPages mNumAppsPages: " + mNumAppsPages + " mNumWidgetPages: " + mNumWidgetPages);
     }
 
     @Override
     public void syncPageItems(int page, boolean immediate) {
+        Log.d(TAG, "6549598 syncPageItems page: " + page + " immediate: " + immediate);
         if (page < mNumAppsPages) {
             syncAppsPageItems(page, immediate);
         } else {
@@ -1558,6 +1756,7 @@
     public void setApps(ArrayList<ApplicationInfo> list) {
         mApps = list;
         Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
+        Log.d(TAG, "6549598 setApps mApps.size(): " + mApps.size());
         updatePageCounts();
 
         // The next layout pass will trigger data-ready if both widgets and apps are set, so 
@@ -1578,8 +1777,10 @@
     @Override
     public void addApps(ArrayList<ApplicationInfo> list) {
         addAppsWithoutInvalidate(list);
+        Log.d(TAG, "6549598 addApps mApps.size(): " + mApps.size() + " list.size(): " + list.size());
         updatePageCounts();
         invalidatePageData();
+        Log.d(TAG, "6549598 addApps mNumAppsPages: " + mNumAppsPages);
     }
     private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
         ComponentName removeComponent = item.intent.getComponent();
@@ -1606,8 +1807,10 @@
     @Override
     public void removeApps(ArrayList<ApplicationInfo> list) {
         removeAppsWithoutInvalidate(list);
+        Log.d(TAG, "6549598 removeApps mApps.size(): " + mApps.size() + " list.size(): " + list.size());
         updatePageCounts();
         invalidatePageData();
+        Log.d(TAG, "6549598 removeApps mNumAppsPages: " + mNumAppsPages);
     }
     @Override
     public void updateApps(ArrayList<ApplicationInfo> list) {
@@ -1616,13 +1819,15 @@
         // place in the list.
         removeAppsWithoutInvalidate(list);
         addAppsWithoutInvalidate(list);
+        Log.d(TAG, "6549598 updateApps mApps.size(): " + mApps.size() + " list.size(): " + list.size());
         updatePageCounts();
-
         invalidatePageData();
+        Log.d(TAG, "6549598 updateApps mNumAppsPages: " + mNumAppsPages);
     }
 
     @Override
     public void reset() {
+        Log.d(TAG, "6549598 reset");
         // If we have reset, then we should not continue to restore the previous state
         mSaveInstanceStateItemIndex = -1;
 
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index e4b5af3..c028ff1 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -31,7 +31,6 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
@@ -80,7 +79,6 @@
     // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
     private final int[] mTmpXY = new int[2];
     private final int[] mTmpPoint = new int[2];
-    private final PointF mTmpPointF = new PointF();
     int[] mTempLocation = new int[2];
 
     boolean[][] mOccupied;
@@ -149,7 +147,7 @@
     static final int LANDSCAPE = 0;
     static final int PORTRAIT = 1;
 
-    private static final float REORDER_HINT_MAGNITUDE = 0.10f;
+    private static final float REORDER_HINT_MAGNITUDE = 0.12f;
     private static final int REORDER_ANIMATION_DURATION = 150;
     private float mReorderHintAnimationMagnitude;
 
@@ -427,7 +425,7 @@
         if (DEBUG_VISUALIZE_OCCUPIED) {
             int[] pt = new int[2];
             ColorDrawable cd = new ColorDrawable(Color.RED);
-            cd.setBounds(0, 0, 80, 80);
+            cd.setBounds(0, 0,  mCellWidth, mCellHeight);
             for (int i = 0; i < mCountX; i++) {
                 for (int j = 0; j < mCountY; j++) {
                     if (mOccupied[i][j]) {
@@ -1706,6 +1704,102 @@
         markCellsForView(r.left, r.top, r.width(), r.height(), occupied, value);
     }
 
+    // This method tries to find a reordering solution which satisfies the push mechanic by trying
+    // to push items in each of the cardinal directions, in an order based on the direction vector
+    // passed.
+    private boolean attemptPushInDirection(ArrayList<View> intersectingViews, Rect occupied,
+            int[] direction, View ignoreView, ItemConfiguration solution) {
+        if ((Math.abs(direction[0]) + Math.abs(direction[1])) > 1) {
+            // If the direction vector has two non-zero components, we try pushing 
+            // separately in each of the components.
+            int temp = direction[1];
+            direction[1] = 0;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+            direction[1] = temp;
+            temp = direction[0];
+            direction[0] = 0;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Revert the direction
+            direction[0] = temp;
+
+            // Now we try pushing in each component of the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            temp = direction[1];
+            direction[1] = 0;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+
+            direction[1] = temp;
+            temp = direction[0];
+            direction[0] = 0;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // revert the direction
+            direction[0] = temp;
+            direction[0] *= -1;
+            direction[1] *= -1;
+            
+        } else {
+            // If the direction vector has a single non-zero component, we push first in the
+            // direction of the vector
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+
+            // Then we try the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Switch the direction back
+            direction[0] *= -1;
+            direction[1] *= -1;
+            
+            // If we have failed to find a push solution with the above, then we try 
+            // to find a solution by pushing along the perpendicular axis.
+
+            // Swap the components
+            int temp = direction[1];
+            direction[1] = direction[0];
+            direction[0] = temp;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+
+            // Then we try the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            if (addViewsToTempLocation(intersectingViews, occupied, direction, true,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Switch the direction back
+            direction[0] *= -1;
+            direction[1] *= -1;
+
+            // Swap the components back
+            temp = direction[1];
+            direction[1] = direction[0];
+            direction[0] = temp;
+        }
+        return false;
+    }
+
     private boolean rearrangementExists(int cellX, int cellY, int spanX, int spanY, int[] direction,
             View ignoreView, ItemConfiguration solution) {
         // Return early if get invalid cell positions
@@ -1737,23 +1831,15 @@
             }
         }
 
-        // We try to move the intersecting views as a block using the push mechanic
-        if (addViewsToTempLocation(mIntersectingViews, mOccupiedRect, direction, true, ignoreView,
+        // First we try to find a solution which respects the push mechanic. That is, 
+        // we try to find a solution such that no displaced item travels through another item
+        // without also displacing that item.
+        if (attemptPushInDirection(mIntersectingViews, mOccupiedRect, direction, ignoreView,
                 solution)) {
             return true;
         }
-        // Try the opposite direction
-        direction[0] *= -1;
-        direction[1] *= -1;
-        if (addViewsToTempLocation(mIntersectingViews, mOccupiedRect, direction, true, ignoreView,
-                solution)) {
-            return true;
-        }
-        // Switch the direction back
-        direction[0] *= -1;
-        direction[1] *= -1;
 
-        // Next we try moving the views as a block , but without requiring the push mechanic
+        // Next we try moving the views as a block, but without requiring the push mechanic.
         if (addViewsToTempLocation(mIntersectingViews, mOccupiedRect, direction, false, ignoreView,
                 solution)) {
             return true;
@@ -1903,7 +1989,6 @@
     // This method starts or changes the reorder hint animations
     private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
         int childCount = mShortcutsAndWidgets.getChildCount();
-        int timeForPriorAnimationToComplete = getMaxCompletionTime();
         for (int i = 0; i < childCount; i++) {
             View child = mShortcutsAndWidgets.getChildAt(i);
             if (child == dragView) continue;
@@ -1912,7 +1997,7 @@
             if (c != null) {
                 ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
                         c.x, c.y, c.spanX, c.spanY);
-                rha.animate(timeForPriorAnimationToComplete);
+                rha.animate();
             }
         }
     }
@@ -1921,12 +2006,14 @@
     // in a temporary state, and hint at where the item will return to.
     class ReorderHintAnimation {
         View child;
-        float deltaX;
-        float deltaY;
+        float finalDeltaX;
+        float finalDeltaY;
+        float initDeltaX;
+        float initDeltaY;
+        float finalScale;
+        float initScale;
         private static final int DURATION = 300;
-        private int repeatCount;
-        private boolean cancelOnCycleComplete = false;
-        ValueAnimator va;
+        Animator a;
 
         public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
                 int spanX, int spanY) {
@@ -1938,74 +2025,89 @@
             final int y1 = mTmpPoint[1];
             final int dX = x1 - x0;
             final int dY = y1 - y0;
-            deltaX = 0;
-            deltaY = 0;
+            finalDeltaX = 0;
+            finalDeltaY = 0;
             if (dX == dY && dX == 0) {
             } else {
                 if (dY == 0) {
-                    deltaX = mReorderHintAnimationMagnitude;
+                    finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
                 } else if (dX == 0) {
-                    deltaY = mReorderHintAnimationMagnitude;
+                    finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
                 } else {
                     double angle = Math.atan( (float) (dY) / dX);
-                    deltaX = (int) (Math.cos(angle) * mReorderHintAnimationMagnitude);
-                    deltaY = (int) (Math.sin(angle) * mReorderHintAnimationMagnitude);
+                    finalDeltaX = (int) (- Math.signum(dX) *
+                            Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
+                    finalDeltaY = (int) (- Math.signum(dY) *
+                            Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
                 }
             }
+            initDeltaX = child.getTranslationX();
+            initDeltaY = child.getTranslationY();
+            finalScale = 1.0f - 4.0f / child.getWidth();
+            initScale = child.getScaleX();
+
             child.setPivotY(child.getMeasuredHeight() * 0.5f);
             child.setPivotX(child.getMeasuredWidth() * 0.5f);
             this.child = child;
         }
 
-        void animate(int delay) {
+        void animate() {
             if (mShakeAnimators.containsKey(child)) {
                 ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
-                oldAnimation.completeAnimation();
+                oldAnimation.cancel();
                 mShakeAnimators.remove(child);
+                if (finalDeltaX == 0 && finalDeltaY == 0) {
+                    completeAnimationImmediately();
+                    return;
+                }
             }
-            if (deltaX == 0 && deltaY == 0) {
+            if (finalDeltaX == 0 && finalDeltaY == 0) {
                 return;
             }
-            va = ValueAnimator.ofFloat(0f, 1f);
+            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            a = va;
             va.setRepeatMode(ValueAnimator.REVERSE);
             va.setRepeatCount(ValueAnimator.INFINITE);
-            va.setDuration((int) (DURATION * (1.0f + Math.random()*.08f)));
+            va.setDuration(DURATION);
+            va.setStartDelay((int) (Math.random() * 60));
             va.addUpdateListener(new AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
                     float r = ((Float) animation.getAnimatedValue()).floatValue();
-                    float x = r * deltaX;
-                    float y = r * deltaY;
+                    float x = r * finalDeltaX + (1 - r) * initDeltaX;
+                    float y = r * finalDeltaY + (1 - r) * initDeltaY;
                     child.setTranslationX(x);
                     child.setTranslationY(y);
-                    float sf = 4.0f / child.getWidth();
-                    float s = 1.0f - r * sf;
+                    float s = r * finalScale + (1 - r) * initScale;
                     child.setScaleX(s);
                     child.setScaleY(s);
                 }
             });
             va.addListener(new AnimatorListenerAdapter() {
                 public void onAnimationRepeat(Animator animation) {
-                    repeatCount++;
                     // We make sure to end only after a full period
-                    if (cancelOnCycleComplete && repeatCount % 2 == 0) {
-                        va.cancel();
-                    }
+                    initDeltaX = 0;
+                    initDeltaY = 0;
+                    initScale = 1.0f;
                 }
             });
-            va.setStartDelay(Math.max(REORDER_ANIMATION_DURATION, delay));
             mShakeAnimators.put(child, this);
             va.start();
         }
 
-
-        private void completeAnimation() {
-            cancelOnCycleComplete = true;
+        private void cancel() {
+            if (a != null) {
+                a.cancel();
+            }
         }
+
         private void completeAnimationImmediately() {
-            va.cancel();
+            if (a != null) {
+                a.cancel();
+            }
 
             AnimatorSet s = new AnimatorSet();
+            a = s;
             s.playTogether(
                 ObjectAnimator.ofFloat(child, "scaleX", 1f),
                 ObjectAnimator.ofFloat(child, "scaleY", 1f),
@@ -2016,16 +2118,6 @@
             s.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
             s.start();
         }
-
-
-        // Returns the time required to complete the current oscillating animation
-        private int completionTime() {
-            if (repeatCount % 2 == 0) {
-                return (int) (va.getDuration() - va.getCurrentPlayTime() + DURATION);
-            } else {
-                return (int) (va.getDuration() - va.getCurrentPlayTime());
-            }
-        }
     }
 
     private void completeAndClearReorderHintAnimations() {
@@ -2035,14 +2127,6 @@
         mShakeAnimators.clear();
     }
 
-    private int getMaxCompletionTime() {
-        int maxTime = 0;
-        for (ReorderHintAnimation a: mShakeAnimators.values()) {
-            maxTime = Math.max(maxTime, a.completionTime());
-        }
-        return maxTime;
-    }
-
     private void commitTempPlacement() {
         for (int i = 0; i < mCountX; i++) {
             for (int j = 0; j < mCountY; j++) {
diff --git a/src/com/android/launcher2/Cling.java b/src/com/android/launcher2/Cling.java
index 5cde0b4..c83ee2f 100644
--- a/src/com/android/launcher2/Cling.java
+++ b/src/com/android/launcher2/Cling.java
@@ -115,6 +115,10 @@
         mIsInitialized = false;
     }
 
+    public String getDrawIdentifier() {
+        return mDrawIdentifier;
+    }
+
     private int[] getPunchThroughPositions() {
         if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)) {
             return new int[]{getMeasuredWidth() / 2, getMeasuredHeight() - (mButtonBarHeight / 2)};
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
index 1edc2ab..949c035 100644
--- a/src/com/android/launcher2/DeleteDropTarget.java
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -39,7 +39,8 @@
 
 public class DeleteDropTarget extends ButtonDropTarget {
     private static int DELETE_ANIMATION_DURATION = 285;
-    private static int FLIND_DELETE_ANIMATION_DURATION = 350;
+    private static int FLING_DELETE_ANIMATION_DURATION = 350;
+    private static float FLING_TO_DELETE_FRICTION = 0.035f;
     private static int MODE_FLING_DELETE_TO_TRASH = 0;
     private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
 
@@ -311,22 +312,22 @@
      * progressively.
      */
     private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
-        private static float FRICTION = 0.93f;
-
         private DragLayer mDragLayer;
         private PointF mVelocity;
         private Rect mFrom;
         private long mPrevTime;
         private boolean mHasOffsetForScale;
+        private float mFriction;
 
         private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
 
         public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
-                long startTime) {
+                long startTime, float friction) {
             mDragLayer = dragLayer;
             mVelocity = vel;
             mFrom = from;
             mPrevTime = startTime;
+            mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
         }
 
         @Override
@@ -352,8 +353,8 @@
             dragView.setTranslationY(mFrom.top);
             dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
 
-            mVelocity.x *= FRICTION;
-            mVelocity.y *= FRICTION;
+            mVelocity.x *= mFriction;
+            mVelocity.y *= mFriction;
             mPrevTime = curTime;
         }
     };
@@ -363,7 +364,8 @@
         final Rect from = new Rect();
         dragLayer.getViewRectRelativeToSelf(d.dragView, from);
 
-        return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime);
+        return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
+                FLING_TO_DELETE_FRICTION);
     }
 
     public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
@@ -385,7 +387,7 @@
 
         final ViewConfiguration config = ViewConfiguration.get(mLauncher);
         final DragLayer dragLayer = mLauncher.getDragLayer();
-        final int duration = FLIND_DELETE_ANIMATION_DURATION;
+        final int duration = FLING_DELETE_ANIMATION_DURATION;
         final long startTime = AnimationUtils.currentAnimationTimeMillis();
 
         // NOTE: Because it takes time for the first frame of animation to actually be
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 1b0ccf5..84f1515 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -62,7 +63,6 @@
     static final int SCROLL_RIGHT = 1;
 
     private static final float MAX_FLING_DEGREES = 35f;
-    private static final int FLING_TO_DELETE_THRESHOLD_Y_VELOCITY = -1500;
 
     private Launcher mLauncher;
     private Handler mHandler;
@@ -146,14 +146,16 @@
      * @param context The application's context.
      */
     public DragController(Launcher launcher) {
+        Resources r = launcher.getResources();
         mLauncher = launcher;
         mHandler = new Handler();
-        mScrollZone = launcher.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
+        mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone);
         mVelocityTracker = VelocityTracker.obtain();
-        mVibrator = (Vibrator)launcher.getSystemService(Context.VIBRATOR_SERVICE);
+        mVibrator = (Vibrator) launcher.getSystemService(Context.VIBRATOR_SERVICE);
 
-        float density = launcher.getResources().getDisplayMetrics().density;
-        mFlingToDeleteThresholdVelocity = (int) (FLING_TO_DELETE_THRESHOLD_Y_VELOCITY * density);
+        float density = r.getDisplayMetrics().density;
+        mFlingToDeleteThresholdVelocity =
+                (int) (r.getInteger(R.integer.config_flingToDeleteMinVelocity) * density);
     }
 
     public boolean dragging() {
diff --git a/src/com/android/launcher2/DrawableStateProxyView.java b/src/com/android/launcher2/DrawableStateProxyView.java
index dac9584..5d2f6e0 100644
--- a/src/com/android/launcher2/DrawableStateProxyView.java
+++ b/src/com/android/launcher2/DrawableStateProxyView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
 
@@ -37,6 +38,7 @@
         this(context, attrs, 0);
     }
 
+
     public DrawableStateProxyView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
@@ -59,4 +61,9 @@
         mView.setPressed(isPressed());
         mView.setHovered(isHovered());
     }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        return false;
+    }
 }
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 92cabe5..db65a31 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -106,6 +106,7 @@
 
     private static String sDefaultFolderName;
     private static String sHintText;
+    private ObjectAnimator mOpenCloseAnimator;
 
     /**
      * Used to inflate the Workspace from XML.
@@ -417,7 +418,8 @@
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+        final ObjectAnimator oa = mOpenCloseAnimator =
+            ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -430,7 +432,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mState = STATE_OPEN;
-
+                setLayerType(LAYER_TYPE_NONE, null);
                 Cling cling = mLauncher.showFirstRunFoldersCling();
                 if (cling != null) {
                     cling.bringToFront();
@@ -439,7 +441,16 @@
             }
         });
         oa.setDuration(mExpandDuration);
-        oa.start();
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+        buildLayer();
+        post(new Runnable() {
+            public void run() {
+                // Check if the animator changed in the meantime
+                if (oa != mOpenCloseAnimator)
+                    return;
+                oa.start();
+            }
+        });
     }
 
     private void sendCustomAccessibilityEvent(int type, String text) {
@@ -465,12 +476,14 @@
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+        final ObjectAnimator oa = mOpenCloseAnimator =
+                ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
                 onCloseComplete();
+                setLayerType(LAYER_TYPE_NONE, null);
                 mState = STATE_SMALL;
             }
             @Override
@@ -481,7 +494,16 @@
             }
         });
         oa.setDuration(mExpandDuration);
-        oa.start();
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+        buildLayer();
+        post(new Runnable() {
+            public void run() {
+                // Check if the animator changed in the meantime
+                if (oa != mOpenCloseAnimator)
+                    return;
+                oa.start();
+            }
+        });
     }
 
     void notifyDataSetChanged() {
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 1e42f1b..aa19545 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -94,15 +95,20 @@
     }
 
     public Drawable getFullResIcon(ResolveInfo info) {
+        return getFullResIcon(info.activityInfo);
+    }
+
+    public Drawable getFullResIcon(ActivityInfo info) {
+
         Resources resources;
         try {
             resources = mPackageManager.getResourcesForApplication(
-                    info.activityInfo.applicationInfo);
+                    info.applicationInfo);
         } catch (PackageManager.NameNotFoundException e) {
             resources = null;
         }
         if (resources != null) {
-            int iconId = info.activityInfo.getIconResource();
+            int iconId = info.getIconResource();
             if (iconId != 0) {
                 return getFullResIcon(resources, iconId);
             }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 84b5003..fb29a41 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,6 +17,8 @@
 
 package com.android.launcher2;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -348,6 +350,7 @@
 
         // Update customization drawer _after_ restoring the states
         if (mAppsCustomizeContent != null) {
+            Log.d(TAG, "6549598 Launcher.onCreate()");
             mAppsCustomizeContent.onPackagesUpdated();
         }
 
@@ -371,6 +374,13 @@
         IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         registerReceiver(mCloseSystemDialogsReceiver, filter);
 
+        updateGlobalIcons();
+
+        // On large interfaces, we want the screen to auto-rotate based on the current orientation
+        unlockScreenOrientation(true);
+    }
+
+    private void updateGlobalIcons() {
         boolean searchVisible = false;
         boolean voiceVisible = false;
         // If we have a saved version of these external icons, we load them up immediately
@@ -393,9 +403,6 @@
             updateAppMarketIcon(sAppMarketIcon[coi]);
         }
         mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, voiceVisible);
-
-        // On large interfaces, we want the screen to auto-rotate based on the current orientation
-        unlockScreenOrientation(true);
     }
 
     private void checkForLocaleChange() {
@@ -679,6 +686,43 @@
             // Resets the previous all apps icon press state
             mAppsCustomizeContent.resetDrawableState();
         }
+        // It is possible that widgets can receive updates while launcher is not in the foreground.
+        // Consequently, the widgets will be inflated in the orientation of the foreground activity
+        // (framework issue). On resuming, we ensure that any widgets are inflated for the current
+        // orientation.
+        reinflateWidgetsIfNecessary();
+
+        // Again, as with the above scenario, it's possible that one or more of the global icons
+        // were updated in the wrong orientation.
+        updateGlobalIcons();
+    }
+
+    void reinflateWidgetsIfNecessary() {
+        for (LauncherAppWidgetInfo info: LauncherModel.getWidgets()) {
+            LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
+            if (lahv != null && lahv.orientationChangedSincedInflation()) {
+                AppWidgetProviderInfo pInfo = lahv.getAppWidgetInfo();
+
+                Workspace workspace = getWorkspace();
+                CellLayout parent = workspace.getParentCellLayoutForView(lahv);
+
+                // It's possible this AppWidgetHostView is associated with a prior Launcher instance
+                // in which case it will not have a parent in the current hierarchy (ie. after rotation).
+                //  In this case we will be re-inflating the widgets anyhow, so it's not a problem.
+                if (parent != null) {
+                    // Remove the current widget which is inflated with the wrong orientation
+                    parent.removeView(lahv);
+                    // Re-inflate the widget using the correct orientation
+                    AppWidgetHostView widget = mAppWidgetHost.createView(this, info.appWidgetId, pInfo);
+
+                    // Add the new widget back
+                    widget.setTag(info);
+                    info.hostView = widget;
+                    getWorkspace().addInScreen(widget, info.container, info.screen,
+                            info.cellX, info.cellY, info.spanX, info.spanY);
+                }
+            }
+        }
     }
 
     @Override
@@ -815,6 +859,7 @@
             mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
             mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
             mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
+            mWaitingForResult = true;
             mRestoring = true;
         }
 
@@ -2224,6 +2269,11 @@
     }
 
     private void dispatchOnLauncherTransitionStart(View v, boolean animated, boolean toWorkspace) {
+        if (toWorkspace) {
+            Log.d(TAG, "6549598 Start animation to workspace");
+        } else {
+            Log.d(TAG, "6549598 Start animation to all apps");
+        }
         if (v instanceof LauncherTransitionable) {
             ((LauncherTransitionable) v).onLauncherTransitionStart(this, animated, toWorkspace);
         }
@@ -2239,6 +2289,11 @@
     }
 
     private void dispatchOnLauncherTransitionEnd(View v, boolean animated, boolean toWorkspace) {
+        if (toWorkspace) {
+            Log.d(TAG, "6549598 End animation to workspace");
+        } else {
+            Log.d(TAG, "6549598 End animation to all apps");
+        }
         if (v instanceof LauncherTransitionable) {
             ((LauncherTransitionable) v).onLauncherTransitionEnd(this, animated, toWorkspace);
         }
@@ -2400,32 +2455,37 @@
                 observer = null;
             }
 
+            final AnimatorSet stateAnimation = mStateAnimation;
+            final Runnable startAnimRunnable = new Runnable() {
+                public void run() {
+                    // Check that mStateAnimation hasn't changed while
+                    // we waited for a layout/draw pass
+                    if (mStateAnimation != stateAnimation)
+                        return;
+                    setPivotsForZoom(toView, scale);
+                    dispatchOnLauncherTransitionStart(fromView, animated, false);
+                    dispatchOnLauncherTransitionStart(toView, animated, false);
+                    mWorkspace.post(new Runnable() {
+                        public void run() {
+                            // Check that mStateAnimation hasn't changed while
+                            // we waited for a layout/draw pass
+                            if (mStateAnimation != stateAnimation)
+                                return;
+                            mStateAnimation.start();
+                        }
+                    });
+                }
+            };
             if (delayAnim) {
-                final AnimatorSet stateAnimation = mStateAnimation;
                 final OnGlobalLayoutListener delayedStart = new OnGlobalLayoutListener() {
                     public void onGlobalLayout() {
-                        mWorkspace.post(new Runnable() {
-                            public void run() {
-                                // Check that mStateAnimation hasn't changed while
-                                // we waited for a layout pass
-                                if (mStateAnimation == stateAnimation) {
-                                    // Need to update pivots for zoom if layout changed
-                                    setPivotsForZoom(toView, scale);
-                                    dispatchOnLauncherTransitionStart(fromView, animated, false);
-                                    dispatchOnLauncherTransitionStart(toView, animated, false);
-                                    mStateAnimation.start();
-                                }
-                            }
-                        });
+                        mWorkspace.post(startAnimRunnable);
                         observer.removeOnGlobalLayoutListener(this);
                     }
                 };
                 observer.addOnGlobalLayoutListener(delayedStart);
             } else {
-                setPivotsForZoom(toView, scale);
-                dispatchOnLauncherTransitionStart(fromView, animated, false);
-                dispatchOnLauncherTransitionStart(toView, animated, false);
-                mStateAnimation.start();
+                startAnimRunnable.run();
             }
         } else {
             toView.setTranslationX(0.0f);
@@ -2536,7 +2596,14 @@
             }
             dispatchOnLauncherTransitionStart(fromView, animated, true);
             dispatchOnLauncherTransitionStart(toView, animated, true);
-            mStateAnimation.start();
+            final Animator stateAnimation = mStateAnimation;
+            mWorkspace.post(new Runnable() {
+                public void run() {
+                    if (stateAnimation != mStateAnimation)
+                        return;
+                    mStateAnimation.start();
+                }
+            });
         } else {
             fromView.setVisibility(View.GONE);
             dispatchOnLauncherTransitionPrepare(fromView, animated, true);
@@ -3516,10 +3583,23 @@
             });
         }
     }
+
+    private boolean skipCustomClingIfNoAccounts() {
+        Cling cling = (Cling) findViewById(R.id.workspace_cling);
+        boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
+        if (customCling) {
+            AccountManager am = AccountManager.get(this);
+            Account[] accounts = am.getAccountsByType("com.google");
+            return accounts.length == 0;
+        }
+        return false;
+    }
+
     public void showFirstRunWorkspaceCling() {
         // Enable the clings only if they have not been dismissed before
         if (isClingsEnabled() &&
-                !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) {
+                !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false) &&
+                !skipCustomClingIfNoAccounts() ) {
             initCling(R.id.workspace_cling, null, false, 0);
         } else {
             removeCling(R.id.workspace_cling);
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index e34196e..9970c76 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -18,10 +18,14 @@
 
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Parcel;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.RemoteViews;
 
 import com.android.launcher.R;
 
@@ -31,9 +35,12 @@
 public class LauncherAppWidgetHostView extends AppWidgetHostView {
     private CheckLongPressHelper mLongPressHelper;
     private LayoutInflater mInflater;
+    private Context mContext;
+    private int mPreviousOrientation;
 
     public LauncherAppWidgetHostView(Context context) {
         super(context);
+        mContext = context;
         mLongPressHelper = new CheckLongPressHelper(this);
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     }
@@ -43,6 +50,21 @@
         return mInflater.inflate(R.layout.appwidget_error, this, false);
     }
 
+    @Override
+    public void updateAppWidget(RemoteViews remoteViews) {
+        // Store the orientation in which the widget was inflated
+        mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
+        super.updateAppWidget(remoteViews);
+    }
+
+    public boolean orientationChangedSincedInflation() {
+        int orientation = mContext.getResources().getConfiguration().orientation;
+        if (mPreviousOrientation != orientation) {
+           return true;
+       }
+       return false;
+    }
+
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // Consume any touch events for ourselves after longpress is triggered
         if (mLongPressHelper.hasPerformedLongPress()) {
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index fc1a26d..1b17ef9 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -377,6 +377,10 @@
         return items;
     }
 
+    static ArrayList<LauncherAppWidgetInfo> getWidgets() {
+        return sAppWidgets;
+    }
+
     /**
      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.
      */
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 93725ce..c820264 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -1673,6 +1673,7 @@
     }
     protected void invalidatePageData(int currentPage, boolean immediateAndOnly) {
         if (!mIsDataReady) {
+            if (this instanceof AppsCustomizePagedView) Log.d(TAG, "6549598 invalidatePageData page: " + currentPage + " not data ready");
             return;
         }
 
@@ -1704,6 +1705,8 @@
             // Load any pages that are necessary for the current window of views
             loadAssociatedPages(mCurrentPage, immediateAndOnly);
             requestLayout();
+
+            if (this instanceof AppsCustomizePagedView) Log.d(TAG, "6549598 invalidatePageData page: " + currentPage);
         }
     }
 
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index e894142..66b7080 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -43,6 +43,7 @@
     ShortPressListener mShortPressListener = null;
     boolean mShortPressTriggered = false;
     static PagedViewWidget sShortpressTarget = null;
+    boolean mIsAppWidget;
 
     public PagedViewWidget(Context context) {
         this(context, null);
@@ -84,6 +85,7 @@
 
     public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info,
             int maxWidth, int[] cellSpan) {
+        mIsAppWidget = true;
         final ImageView image = (ImageView) findViewById(R.id.widget_preview);
         if (maxWidth > -1) {
             image.setMaxWidth(maxWidth);
@@ -100,6 +102,7 @@
     }
 
     public void applyFromResolveInfo(PackageManager pm, ResolveInfo info) {
+        mIsAppWidget = false;
         CharSequence label = info.loadLabel(pm);
         final ImageView image = (ImageView) findViewById(R.id.widget_preview);
         image.setContentDescription(label);
@@ -115,16 +118,25 @@
         final ImageView i = (ImageView) findViewById(R.id.widget_preview);
         int[] maxSize = new int[2];
         maxSize[0] = i.getWidth() - i.getPaddingLeft() - i.getPaddingRight();
-        maxSize[1] = i.getHeight() - i.getPaddingBottom() - i.getPaddingTop();
+        maxSize[1] = i.getHeight() - i.getPaddingTop();
         return maxSize;
     }
 
     void applyPreview(FastBitmapDrawable preview, int index) {
         final PagedViewWidgetImageView image =
-                (PagedViewWidgetImageView) findViewById(R.id.widget_preview);
+            (PagedViewWidgetImageView) findViewById(R.id.widget_preview);
         if (preview != null) {
             image.mAllowRequestLayout = false;
             image.setImageDrawable(preview);
+            if (mIsAppWidget) {
+                // center horizontally
+                int[] imageSize = getPreviewSize();
+                int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2;
+                image.setPadding(image.getPaddingLeft() + centerAmount,
+                        image.getPaddingTop(),
+                        image.getPaddingRight(),
+                        image.getPaddingBottom());
+            }
             image.setAlpha(1f);
             image.mAllowRequestLayout = true;
         }
diff --git a/src/com/android/launcher2/PagedViewWidgetImageView.java b/src/com/android/launcher2/PagedViewWidgetImageView.java
index 844b337..22db0ab 100644
--- a/src/com/android/launcher2/PagedViewWidgetImageView.java
+++ b/src/com/android/launcher2/PagedViewWidgetImageView.java
@@ -17,6 +17,8 @@
 package com.android.launcher2;
 
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Insets;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
@@ -34,4 +36,22 @@
             super.requestLayout();
         }
     }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+
+        Insets insets = Insets.NONE;
+        if (getBackground() != null) {
+            insets = getBackground().getLayoutInsets();
+        }
+        canvas.save();
+        canvas.clipRect(getScrollX() + getPaddingLeft() + insets.left,
+                getScrollY() + getPaddingTop() + insets.top,
+                getScrollX() + getRight() - getLeft() - getPaddingRight() - insets.right,
+                getScrollY() + getBottom() - getTop() - getPaddingBottom() - insets.bottom);
+
+        super.onDraw(canvas);
+        canvas.restore();
+
+    }
 }
diff --git a/src/com/android/launcher2/PendingAddItemInfo.java b/src/com/android/launcher2/PendingAddItemInfo.java
index 26e946e..9a133ed 100644
--- a/src/com/android/launcher2/PendingAddItemInfo.java
+++ b/src/com/android/launcher2/PendingAddItemInfo.java
@@ -19,6 +19,7 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
 import android.os.Parcelable;
 
 /**
@@ -31,6 +32,20 @@
     ComponentName componentName;
 }
 
+class PendingAddShortcutInfo extends PendingAddItemInfo {
+
+    ActivityInfo shortcutActivityInfo;
+
+    public PendingAddShortcutInfo(ActivityInfo activityInfo) {
+        shortcutActivityInfo = activityInfo;
+    }
+
+    @Override
+    public String toString() {
+        return "Shortcut: " + shortcutActivityInfo.packageName;
+    }
+}
+
 class PendingAddWidgetInfo extends PendingAddItemInfo {
     int minWidth;
     int minHeight;
@@ -81,4 +96,9 @@
         minSpanX = copy.minSpanX;
         minSpanY = copy.minSpanY;
     }
+
+    @Override
+    public String toString() {
+        return "Widget: " + componentName.toShortString();
+    }
 }
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
index a01fd3a..77681a8 100644
--- a/src/com/android/launcher2/SearchDropTargetBar.java
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -18,7 +18,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Rect;
@@ -26,7 +25,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 
 import com.android.launcher.R;
@@ -40,10 +38,10 @@
     private static final int sTransitionInDuration = 200;
     private static final int sTransitionOutDuration = 175;
 
-    private ObjectAnimator mDropTargetBarFadeInAnim;
-    private ObjectAnimator mDropTargetBarFadeOutAnim;
-    private ObjectAnimator mQSBSearchBarFadeInAnim;
-    private ObjectAnimator mQSBSearchBarFadeOutAnim;
+    private ObjectAnimator mDropTargetBarAnim;
+    private ObjectAnimator mQSBSearchBarAnim;
+    private static final AccelerateInterpolator sAccelerateInterpolator =
+            new AccelerateInterpolator();
 
     private boolean mIsSearchBarHidden;
     private View mQSBSearchBar;
@@ -75,28 +73,19 @@
         mDeleteDropTarget.setLauncher(launcher);
     }
 
-    // This sets up the view for the animation
     private void prepareStartAnimation(View v) {
-        // Enable the hw layers (which will be disabled in the onAnimationEnd callback below
+        // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
+        // callback below)
         v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         v.buildLayer();
     }
 
-    private void prepareAnimation(ObjectAnimator in, ObjectAnimator out, final View v) {
-        in.setInterpolator(new AccelerateInterpolator());
-        in.setDuration(sTransitionInDuration);
-        in.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                v.setVisibility(View.VISIBLE);
-            }
-        });
-        out.setInterpolator(new AccelerateInterpolator());
-        out.setDuration(sTransitionOutDuration);
-        out.addListener(new AnimatorListenerAdapter() {
+    private void setupAnimation(ObjectAnimator anim, final View v) {
+        anim.setInterpolator(sAccelerateInterpolator);
+        anim.setDuration(sTransitionInDuration);
+        anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                v.setVisibility(View.INVISIBLE);
                 v.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
@@ -122,64 +111,55 @@
         // Create the various fade animations
         if (mEnableDropDownDropTargets) {
             mDropTargetBar.setTranslationY(-mBarHeight);
-            mDropTargetBarFadeInAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY", 0f);
-            mDropTargetBarFadeOutAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY",
-                    -mBarHeight);
-            mQSBSearchBarFadeInAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY", 0);
-            mQSBSearchBarFadeOutAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY",
+            mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY",
+                    -mBarHeight, 0f);
+            mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY", 0,
                     -mBarHeight);
         } else {
             mDropTargetBar.setAlpha(0f);
-            mDropTargetBarFadeInAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 1f);
-            mDropTargetBarFadeOutAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f);
-            mQSBSearchBarFadeInAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 1f);
-            mQSBSearchBarFadeOutAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 0f);
+            mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
+            mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
         }
-        prepareAnimation(mDropTargetBarFadeInAnim, mDropTargetBarFadeOutAnim, mDropTargetBar);
-        prepareAnimation(mQSBSearchBarFadeInAnim, mQSBSearchBarFadeOutAnim, mQSBSearchBar);
+        setupAnimation(mDropTargetBarAnim, mDropTargetBar);
+        setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
     }
 
     public void finishAnimations() {
-        mDropTargetBarFadeInAnim.end();
-        mDropTargetBarFadeOutAnim.end();
-        mQSBSearchBarFadeInAnim.end();
-        mQSBSearchBarFadeOutAnim.end();
-    }
-
-    private void cancelSearchBarAnimations() {
-        mQSBSearchBarFadeInAnim.cancel();
-        mQSBSearchBarFadeOutAnim.cancel();
+        prepareStartAnimation(mDropTargetBar);
+        mDropTargetBarAnim.reverse();
+        prepareStartAnimation(mQSBSearchBar);
+        mQSBSearchBarAnim.reverse();
     }
 
     /*
      * Shows and hides the search bar.
      */
     public void showSearchBar(boolean animated) {
-        cancelSearchBarAnimations();
+        if (!mIsSearchBarHidden) return;
         if (animated) {
             prepareStartAnimation(mQSBSearchBar);
-            mQSBSearchBarFadeInAnim.start();
+            mQSBSearchBarAnim.reverse();
         } else {
-            mQSBSearchBar.setVisibility(View.VISIBLE);
+            mQSBSearchBarAnim.cancel();
             if (mEnableDropDownDropTargets) {
                 mQSBSearchBar.setTranslationY(0);
             } else {
-                mQSBSearchBar.setAlpha(1f);
+                mDropTargetBar.setAlpha(1f);
             }
         }
         mIsSearchBarHidden = false;
     }
     public void hideSearchBar(boolean animated) {
-        cancelSearchBarAnimations();
+        if (mIsSearchBarHidden) return;
         if (animated) {
             prepareStartAnimation(mQSBSearchBar);
-            mQSBSearchBarFadeOutAnim.start();
+            mQSBSearchBarAnim.start();
         } else {
-            mQSBSearchBar.setVisibility(View.INVISIBLE);
+            mQSBSearchBarAnim.cancel();
             if (mEnableDropDownDropTargets) {
-                mQSBSearchBar.setTranslationY(0);
+                mQSBSearchBar.setTranslationY(-mBarHeight);
             } else {
-                mQSBSearchBar.setAlpha(0f);
+                mDropTargetBar.setAlpha(0f);
             }
         }
         mIsSearchBarHidden = true;
@@ -202,12 +182,10 @@
     public void onDragStart(DragSource source, Object info, int dragAction) {
         // Animate out the QSB search bar, and animate in the drop target bar
         prepareStartAnimation(mDropTargetBar);
-        mDropTargetBarFadeOutAnim.cancel();
-        mDropTargetBarFadeInAnim.start();
+        mDropTargetBarAnim.start();
         if (!mIsSearchBarHidden) {
             prepareStartAnimation(mQSBSearchBar);
-            mQSBSearchBarFadeInAnim.cancel();
-            mQSBSearchBarFadeOutAnim.start();
+            mQSBSearchBarAnim.start();
         }
     }
 
@@ -220,12 +198,10 @@
         if (!mDeferOnDragEnd) {
             // Restore the QSB search bar, and animate out the drop target bar
             prepareStartAnimation(mDropTargetBar);
-            mDropTargetBarFadeInAnim.cancel();
-            mDropTargetBarFadeOutAnim.start();
+            mDropTargetBarAnim.reverse();
             if (!mIsSearchBarHidden) {
                 prepareStartAnimation(mQSBSearchBar);
-                mQSBSearchBarFadeOutAnim.cancel();
-                mQSBSearchBarFadeInAnim.start();
+                mQSBSearchBarAnim.reverse();
             }
         } else {
             mDeferOnDragEnd = false;
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 905ad8a..ba51889 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -2194,6 +2194,9 @@
                     resizeOnDrop = true;
                     item.spanX = resultSpan[0];
                     item.spanY = resultSpan[1];
+                    AppWidgetHostView awhv = (AppWidgetHostView) cell;
+                    AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
+                            resultSpan[1]);
                 }
 
                 if (mCurrentPage != screen && !hasMovedIntoHotseat) {
@@ -2767,7 +2770,8 @@
             ItemInfo info = (ItemInfo) d.dragInfo;
 
             mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
-                    (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
+                    (int) mDragViewVisualCenter[1], item.spanX, item.spanY,
+                    mDragTargetLayout, mTargetCell);
 
             setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]);
 
@@ -2787,11 +2791,6 @@
                 minSpanY = item.minSpanY;
             }
 
-            int[] reorderPosition = new int[2];
-            reorderPosition = findNearestArea((int) mDragViewVisualCenter[0],
-                    (int) mDragViewVisualCenter[1], item.spanX, item.spanY, mDragTargetLayout,
-                    reorderPosition);
-
             boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
                     mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
                     item.spanY, child, mTargetCell);
@@ -2802,8 +2801,9 @@
                         mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
                         d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
             } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
-                    && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderPosition[0] ||
-                    mLastReorderY != reorderPosition[1])) {
+                    && !mReorderAlarm.alarmPending() && (mLastReorderX != mTargetCell[0] ||
+                    mLastReorderY != mTargetCell[1])) {
+
                 // Otherwise, if we aren't adding to or creating a folder and there's no pending
                 // reorder, then we schedule a reorder
                 ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
@@ -2839,7 +2839,6 @@
 
         if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
             mDragOverFolderIcon = ((FolderIcon) dragOverView);
-            mAddToExistingFolderOnDrop = true;
             mDragOverFolderIcon.onDragEnter(info);
             if (targetLayout != null) {
                 targetLayout.clearDragOutlines();
@@ -3139,7 +3138,7 @@
 
     private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
             DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell,
-            boolean external) {
+            boolean external, boolean scale) {
         // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
         // location and size on the home screen.
         int spanX = info.spanX;
@@ -3153,8 +3152,16 @@
         float cellLayoutScale =
                 mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc);
         resetTransitionTransform(layout);
-        float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
-        float dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+
+        float dragViewScaleX;
+        float dragViewScaleY;
+        if (scale) {
+            dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
+            dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+        } else {
+            dragViewScaleX = 1f;
+            dragViewScaleY = 1f;
+        }
 
         // The animation will scale the dragView about its center, so we need to center about
         // the final location.
@@ -3173,14 +3180,16 @@
 
         int[] finalPos = new int[2];
         float scaleXY[] = new float[2];
+        boolean scalePreview = !(info instanceof PendingAddShortcutInfo);
         getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
-                external);
+                external, scalePreview);
 
         Resources res = mLauncher.getResources();
         int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
 
         // In the case where we've prebound the widget, we remove it from the DragLayer
         if (finalView instanceof AppWidgetHostView && external) {
+            Log.d(TAG, "6557954 Animate widget drop, final view is appWidgetHostView");
             mLauncher.getDragLayer().removeView(finalView);
         }
         if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {