am ec3aad2e: (-s ours) Merge commit \'d5c6745b\' into klp-dev-plus-aosp

* commit 'ec3aad2e30ead7923f659c197c57f843cc55c913':
  Tightening migration conditions. (Bug 11973614)
diff --git a/Android.mk b/Android.mk
index dbce33f..110117b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,7 +36,7 @@
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
 
-LOCAL_SDK_VERSION := 19
+LOCAL_SDK_VERSION := 21
 
 LOCAL_PACKAGE_NAME := Launcher3
 #LOCAL_CERTIFICATE := shared
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 36fa4c1..591d9b6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,13 +20,9 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.launcher3">
-    <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="16"/>
+    <uses-sdk android:targetSdkVersion="21" android:minSdkVersion="16"/>
 
     <permission
-        android:name="com.android.launcher3.permission.PRELOAD_WORKSPACE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="system|signature" />
-    <permission
         android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="dangerous"
@@ -47,14 +43,16 @@
     <permission
         android:name="com.android.launcher3.permission.WRITE_SETTINGS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
+        android:protectionLevel="signatureOrSystem"
         android:label="@string/permlab_write_settings"
         android:description="@string/permdesc_write_settings"/>
-
     <permission
         android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS"
         android:protectionLevel="signature"
         />
+    <permission
+        android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST"
+        android:protectionLevel="signatureOrSystem" />
 
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
@@ -63,19 +61,26 @@
     <uses-permission android:name="android.permission.BIND_APPWIDGET" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
     <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
     <uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
     <uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
     <uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
+    <uses-permission android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST" />
 
     <application
         android:name="com.android.launcher3.LauncherApplication"
-        android:label="@string/application_name"
-        android:icon="@mipmap/ic_launcher_home"
+        android:allowBackup="@bool/enable_backup"
+        android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
         android:hardwareAccelerated="true"
+        android:icon="@mipmap/ic_launcher_home"
+        android:label="@string/application_name"
         android:largeHeap="@bool/config_largeHeap"
-        android:supportsRtl="true">
+        android:restoreAnyVersion="true"
+        android:supportsRtl="true" >
+
         <activity
             android:name="com.android.launcher3.Launcher"
             android:launchMode="singleTask"
@@ -106,7 +111,7 @@
 
         <activity
             android:name="com.android.launcher3.LauncherWallpaperPickerActivity"
-            android:theme="@style/Theme.WallpaperCropper"
+            android:theme="@style/Theme.WallpaperPicker"
             android:label="@string/pick_wallpaper"
             android:icon="@mipmap/ic_launcher_wallpaper"
             android:finishOnCloseSystemDialogs="true"
@@ -152,15 +157,6 @@
             >
         </service>
 
-        <!-- Intent received used to prepopulate the default workspace. -->
-        <receiver
-            android:name="com.android.launcher3.PreloadReceiver"
-            android:permission="com.android.launcher3.permission.PRELOAD_WORKSPACE">
-            <intent-filter>
-                <action android:name="com.android.launcher3.action.PRELOAD_WORKSPACE" />
-            </intent-filter>
-        </receiver>
-
         <receiver
             android:name="com.android.launcher3.WallpaperChangedReceiver">
             <intent-filter>
@@ -171,18 +167,25 @@
         <!-- Intent received used to install shortcuts from other applications -->
         <receiver
             android:name="com.android.launcher3.InstallShortcutReceiver"
-            android:permission="com.android.launcher3.permission.INSTALL_SHORTCUT">
+            android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
             <intent-filter>
-                <action android:name="com.android.launcher3.action.INSTALL_SHORTCUT" />
+                <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
             </intent-filter>
         </receiver>
 
         <!-- Intent received used to uninstall shortcuts from other applications -->
         <receiver
             android:name="com.android.launcher3.UninstallShortcutReceiver"
-            android:permission="com.android.launcher3.permission.UNINSTALL_SHORTCUT">
+            android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
             <intent-filter>
-                <action android:name="com.android.launcher3.action.UNINSTALL_SHORTCUT" />
+                <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intent received used to initialize a restored widget -->
+        <receiver android:name="com.android.launcher3.AppWidgetsRestoredReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_HOST_RESTORED"/>
             </intent-filter>
         </receiver>
 
@@ -204,6 +207,12 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.launcher3.StartupReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
         <!-- The settings provider contains Home's data, like the workspace favorites -->
         <provider
             android:name="com.android.launcher3.LauncherProvider"
diff --git a/WallpaperPicker/res/drawable-xxhdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-xxhdpi/ic_actionbar_accept.png
new file mode 100755
index 0000000..d9ad51c
--- /dev/null
+++ b/WallpaperPicker/res/drawable-xxhdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
index 1622742..8e349b7 100644
--- a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -18,17 +18,15 @@
 */
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="?android:actionButtonStyle"
+<com.android.launcher3.AlphaDisableableButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/ActionBarSetWallpaperStyle"
+    android:id="@+id/set_wallpaper_button"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-    <TextView style="?android:actionBarTabTextStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="start|center_vertical"
-        android:paddingRight="20dp"
-        android:drawableLeft="@drawable/ic_actionbar_accept"
-        android:drawablePadding="8dp"
-        android:gravity="center_vertical"
-        android:text="@string/wallpaper_instructions" />
-</FrameLayout>
+    android:layout_height="match_parent"
+    android:paddingRight="20dp"
+    android:drawableLeft="@drawable/ic_actionbar_accept"
+    android:drawablePadding="8dp"
+    android:gravity="start|center_vertical"
+    android:text="@string/wallpaper_instructions">
+</com.android.launcher3.AlphaDisableableButton>
diff --git a/WallpaperPicker/res/values-af/strings.xml b/WallpaperPicker/res/values-af/strings.xml
new file mode 100644
index 0000000..c17d26b
--- /dev/null
+++ b/WallpaperPicker/res/values-af/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Stel muurpapier"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Kon nie prent laai nie"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Kon nie prent as muurpapier laai nie"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d gekies"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d gekies"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d gekies"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Muurpapier %1$d van %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Het <xliff:g id="LABEL">%1$s</xliff:g> gekies"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Vee uit"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Kies prent"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Muurpapiere"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Snoei muurpapier"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-am/strings.xml b/WallpaperPicker/res/values-am/strings.xml
new file mode 100644
index 0000000..59c3bf7
--- /dev/null
+++ b/WallpaperPicker/res/values-am/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"ልጣፍ  አዘጋጅ"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"ምስሉን መጫን አልተቻለም"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"ምስሉን እንደ ግድግዳ ወረቀት መጫን አልተቻለም"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d ተመርጧል"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d ተመርጧል"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d ተመርጧል"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ልጣፍ  %1$d የ%2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ተመርጧል"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"ሰርዝ"</string>
+    <string name="pick_image" msgid="6704438906027442697">"ምስል ይምረጡ"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"የግድግዳ ወረቀቶች"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"ልጣፍ  ይከርክሙ"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ar/strings.xml b/WallpaperPicker/res/values-ar/strings.xml
new file mode 100644
index 0000000..2075cc8
--- /dev/null
+++ b/WallpaperPicker/res/values-ar/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"تعيين الخلفية"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"تعذر تحميل الصورة"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"تعذر تحميل الصورة كخلفية"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"‏تم تحديد %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"‏تم تحديد %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"‏تم تحديد %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏الخلفية %1$d من %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"تم تحديد <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"حذف"</string>
+    <string name="pick_image" msgid="6704438906027442697">"اختيار صورة"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"الخلفيات"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"اقتصاص الخلفية"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-bg/strings.xml b/WallpaperPicker/res/values-bg/strings.xml
new file mode 100644
index 0000000..ce4fc65
--- /dev/null
+++ b/WallpaperPicker/res/values-bg/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Задаване на тапета"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Изображението не можа да бъде заредено"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Изображението не можа да бъде заредено като тапет"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Избрахте %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Избрахте %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Избрахте %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Тапет %1$d от %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Избрахте <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Изтриване"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Избиране на изображение"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Тапети"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Подрязване на тапета"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ca/strings.xml b/WallpaperPicker/res/values-ca/strings.xml
new file mode 100644
index 0000000..89de81c
--- /dev/null
+++ b/WallpaperPicker/res/values-ca/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Estableix el fons de pantalla"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"No s\'ha pogut carregar la imatge."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"No s\'ha pogut carregar la imatge com a fons de pantalla."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Seleccionats: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Seleccionats: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Seleccionats: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fons de pantalla %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"S\'ha seleccionat <xliff:g id="LABEL">%1$s</xliff:g>."</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Suprimeix"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Tria una imatge"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fons de pantalla"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Retallar fons de pantalla"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-cs/strings.xml b/WallpaperPicker/res/values-cs/strings.xml
new file mode 100644
index 0000000..a07b9ed
--- /dev/null
+++ b/WallpaperPicker/res/values-cs/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Nastavit jako tapetu"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Obrázek nelze načíst."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Obrázek nelze načíst jako tapetu."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Vybráno: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Vybráno: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Vybráno: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Vybrána položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Smazat"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Vybrat obrázek"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Oříznutí tapety"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-da/strings.xml b/WallpaperPicker/res/values-da/strings.xml
new file mode 100644
index 0000000..5b233e1
--- /dev/null
+++ b/WallpaperPicker/res/values-da/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Angiv baggrund"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Billedet kunne ikke indlæses"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Billedet kunne ikke indlæses som baggrund"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d er valgt"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d er valgt"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d er valgt"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Baggrund %1$d af %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> blev valgt"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Slet"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Vælg et billede"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Baggrunde"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Beskær baggrunden"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-de/strings.xml b/WallpaperPicker/res/values-de/strings.xml
new file mode 100644
index 0000000..11c1cac
--- /dev/null
+++ b/WallpaperPicker/res/values-de/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Hintergrund auswählen"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Bild konnte nicht geladen werden."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Bild konnte nicht als Hintergrund geladen werden."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d ausgewählt"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d ausgewählt"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d ausgewählt"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Hintergrund %1$d von %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ausgewählt"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Löschen"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Bild auswählen"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Hintergründe"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Hintergrund zuschneiden"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-el/strings.xml b/WallpaperPicker/res/values-el/strings.xml
new file mode 100644
index 0000000..8e1e78f
--- /dev/null
+++ b/WallpaperPicker/res/values-el/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Ορισμός ταπετσαρίας"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Δεν ήταν δυνατή η φόρτωση της εικόνας"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Δεν ήταν δυνατή η φόρτωση της εικόνας ως ταπετσαρία"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d επιλεγμένα"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d επιλεγμένα"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d επιλεγμένα"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Ταπετσαρία %1$d από %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Επιλέχθηκε το <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Διαγραφή"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Επιλογή εικόνας"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Ταπετσαρίες"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Περικοπή ταπετσαρίας"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-en-rGB/strings.xml b/WallpaperPicker/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..c057c0c
--- /dev/null
+++ b/WallpaperPicker/res/values-en-rGB/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Set wallpaper"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Couldn\'t load image"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Couldn\'t load image as wallpaper"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selected"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selected"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selected"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d of %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Delete"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pick image"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-en-rIN/strings.xml b/WallpaperPicker/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..c057c0c
--- /dev/null
+++ b/WallpaperPicker/res/values-en-rIN/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Set wallpaper"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Couldn\'t load image"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Couldn\'t load image as wallpaper"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selected"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selected"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selected"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d of %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Delete"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pick image"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-es-rUS/strings.xml b/WallpaperPicker/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..768385b
--- /dev/null
+++ b/WallpaperPicker/res/values-es-rUS/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Establecer como fondo de pantalla"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"No se pudo cargar la imagen."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"No se pudo cargar la imagen como fondo de pantalla."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d seleccionado"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d seleccionado"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d seleccionados"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fondo de pantalla %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Elegir imagen"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-es/strings.xml b/WallpaperPicker/res/values-es/strings.xml
new file mode 100644
index 0000000..702b6d4
--- /dev/null
+++ b/WallpaperPicker/res/values-es/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Establecer fondo"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"No se ha podido cargar la imagen"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"No se ha podido cargar la imagen como fondo de pantalla"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Seleccionados: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Seleccionados: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Seleccionados: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fondo de pantalla %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Seleccionar imagen"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-et-rEE/strings.xml b/WallpaperPicker/res/values-et-rEE/strings.xml
new file mode 100644
index 0000000..c09e223
--- /dev/null
+++ b/WallpaperPicker/res/values-et-rEE/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Määra taustapilt"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Kujutist ei õnnestunud laadida"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Kujutist ei õnnestunud taustapildina laadida"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Valitud on %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Valitud on %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Valitud on %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d/%2$d taustapildist"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Valitud on <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Kustuta"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Vali kujutis"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Taustapildid"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Taustapildi kärpimine"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-fa/strings.xml b/WallpaperPicker/res/values-fa/strings.xml
new file mode 100644
index 0000000..eb330b5
--- /dev/null
+++ b/WallpaperPicker/res/values-fa/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"تنظیم کاغذدیواری"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"تصویر بارگیری نشد"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"تصویر به عنوان کاغذدیواری بارگیری نشد"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"‏%1$d انتخاب شد"</item>
+    <item quantity="one" msgid="8409622005831789373">"‏%1$d انتخاب شد"</item>
+    <item quantity="other" msgid="479468347731745357">"‏%1$d انتخاب شد"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏کاغذدیواری %1$d از %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> انتخاب شده است"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"حذف"</string>
+    <string name="pick_image" msgid="6704438906027442697">"انتخاب تصویر"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"کاغذدیواری‌ها"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"برش کاغذدیواری"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-fi/strings.xml b/WallpaperPicker/res/values-fi/strings.xml
new file mode 100644
index 0000000..0fa4b7b
--- /dev/null
+++ b/WallpaperPicker/res/values-fi/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Aseta taustakuva"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Kuvan lataus epäonnistui"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Kuvaa ei voitu ladata taustakuvaksi"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d valittu"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d valittu"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d valittu"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Taustakuva %1$d/%2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Valittu: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Poista"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Valitse kuva"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Taustakuvat"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Rajaa taustakuva"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-fr-rCA/strings.xml b/WallpaperPicker/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..e956706
--- /dev/null
+++ b/WallpaperPicker/res/values-fr-rCA/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Définir le fond d\'écran"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Impossible de charger l\'image"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossible de charger l\'image comme fond d\'écran"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d sélectionné"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d sélectionné"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d sélectionné(s)"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fond d\'écran %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Sélection : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Supprimer"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Choisir une image"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Rogner le fond d\'écran"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-fr/strings.xml b/WallpaperPicker/res/values-fr/strings.xml
new file mode 100644
index 0000000..ea07db1
--- /dev/null
+++ b/WallpaperPicker/res/values-fr/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Définir comme fond d\'écran"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Impossible de charger l\'image."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossible de charger l\'image comme fond d\'écran."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d élément sélectionné"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d élément sélectionné"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d éléments sélectionnés"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fond d\'écran %1$d sur %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> sélectionné"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Supprimer"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Sélectionner une image"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Rogner le fond d\'écran"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-hi/strings.xml b/WallpaperPicker/res/values-hi/strings.xml
new file mode 100644
index 0000000..fcb252e
--- /dev/null
+++ b/WallpaperPicker/res/values-hi/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"वॉलपेपर सेट करें"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"चित्र लोड नहीं किया जा सका"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"चित्र को वॉलपेपर के रूप में लोड नहीं किया जा सका"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d चयनित"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d चयनित"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d चयनित"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"वॉलपेपर %2$d में से %1$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"चयनित <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"हटाएं"</string>
+    <string name="pick_image" msgid="6704438906027442697">"चित्र चुनें"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"वॉलपेपर"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"वॉलपेपर काटें"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-hr/strings.xml b/WallpaperPicker/res/values-hr/strings.xml
new file mode 100644
index 0000000..ff2eed2
--- /dev/null
+++ b/WallpaperPicker/res/values-hr/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Postavi pozadinsku sliku"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Nije moguće učitati sliku"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Nije moguće učitati sliku kao pozadinsku sliku"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Odabrano je %1$d stavki"</item>
+    <item quantity="one" msgid="8409622005831789373">"Odabrana je %1$d stavka"</item>
+    <item quantity="other" msgid="479468347731745357">"Odabrano stavki: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. pozadinska slika od %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Odabrana je <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Odaberi sliku"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Pozadinske slike"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Obrezivanje pozadinske slike"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-hu/strings.xml b/WallpaperPicker/res/values-hu/strings.xml
new file mode 100644
index 0000000..703aa12
--- /dev/null
+++ b/WallpaperPicker/res/values-hu/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Háttérkép beállítása"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"A kép betöltése nem sikerült"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"A kép betöltése háttérképként nem sikerült"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d kiválasztva"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d kiválasztva"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d kiválasztva"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d/%2$d. háttérkép"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> kiválasztva"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Törlés"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Kép kiválasztása"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Háttérképek"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Háttérkép körbevágása"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-hy-rAM/strings.xml b/WallpaperPicker/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000..f3891dd
--- /dev/null
+++ b/WallpaperPicker/res/values-hy-rAM/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Սահմանել պաստառը"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Չհաջողվեց բեռնել նկարը"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Չհաջողվեց նկարը սահմանել որպես պաստառ"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d ընտրված"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d ընտրված"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d ընտրված"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d պաստառ՝ %2$d-ից"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Ընտրված է <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Ջնջել"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Ընտրել պատկեր"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Պաստառներ"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Եզրատել պաստառը"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-in/strings.xml b/WallpaperPicker/res/values-in/strings.xml
new file mode 100644
index 0000000..f216cf3
--- /dev/null
+++ b/WallpaperPicker/res/values-in/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Setel wallpaper"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Tidak dapat memuat gambar"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Tidak dapat memuat gambar sebagai wallpaper"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d dipilih"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d dipilih"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d dipilih"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d dari %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> terpilih"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Hapus"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pilih gambar"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpaper"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas wallpaper"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-it/strings.xml b/WallpaperPicker/res/values-it/strings.xml
new file mode 100644
index 0000000..c29946f
--- /dev/null
+++ b/WallpaperPicker/res/values-it/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Imposta sfondo"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Impossibile caricare l\'immagine"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossibile caricare l\'immagine come sfondo"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selezionati"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selezionato"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selezionati"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Sfondo %1$d di %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Elemento selezionato: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Elimina"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Scegli l\'immagine"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Sfondi"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Ritaglia sfondo"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-iw/strings.xml b/WallpaperPicker/res/values-iw/strings.xml
new file mode 100644
index 0000000..ddc96e9
--- /dev/null
+++ b/WallpaperPicker/res/values-iw/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"הגדר טפט"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"לא ניתן היה לטעון את התמונה"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"לא ניתן היה לטעון את התמונה כטפט"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"‏%1$d נבחרו"</item>
+    <item quantity="one" msgid="8409622005831789373">"‏%1$d נבחרו"</item>
+    <item quantity="other" msgid="479468347731745357">"‏%1$d נבחרו"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏טפט %1$d מתוך %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"בחרת <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"מחק"</string>
+    <string name="pick_image" msgid="6704438906027442697">"בחר תמונה"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"טפטים"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"חתוך את הטפט"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ja/strings.xml b/WallpaperPicker/res/values-ja/strings.xml
new file mode 100644
index 0000000..80b0944
--- /dev/null
+++ b/WallpaperPicker/res/values-ja/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"壁紙を設定"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"画像を読み込めませんでした"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"画像を壁紙として読み込めませんでした"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d個選択済み"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d個選択済み"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d個選択済み"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"壁紙: %1$d/%2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"選択: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"削除"</string>
+    <string name="pick_image" msgid="6704438906027442697">"画像を選択"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"壁紙"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"壁紙のトリミング"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ka-rGE/strings.xml b/WallpaperPicker/res/values-ka-rGE/strings.xml
new file mode 100644
index 0000000..2f59712
--- /dev/null
+++ b/WallpaperPicker/res/values-ka-rGE/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"ფონის დაყენება"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"სურათი ვერ ჩაიტვირთა."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"სურათი ფონად ვერ ჩაიტვირთა."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"არჩეულია %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"არჩეულია %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"არჩეულია %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ფონი %1$d %2$d-დან"</string>
+    <string name="announce_selection" msgid="123723511662250539">"არჩეული <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"წაშლა"</string>
+    <string name="pick_image" msgid="6704438906027442697">"სურათის ამორჩევა"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"ფონები"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"ფონის ჩამოჭრა"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-km-rKH/strings.xml b/WallpaperPicker/res/values-km-rKH/strings.xml
new file mode 100644
index 0000000..4172235
--- /dev/null
+++ b/WallpaperPicker/res/values-km-rKH/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"កំណត់​ផ្ទាំង​រូបភាព"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"មិន​អាច​ផ្ទុក​រូបភាព"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"មិន​អាច​ផ្ទុក​រូបភាព​ជា​ផ្ទាំង​រូបភាព"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"បាន​ជ្រើស %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"បាន​ជ្រើស %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"បាន​ជ្រើស %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ផ្ទាំង​រូបភាព %1$d នៃ %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"បាន​ជ្រើស <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"លុប"</string>
+    <string name="pick_image" msgid="6704438906027442697">"ជ្រើស​យក​រូបភាព"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"ផ្ទាំង​រូបភាព"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"ច្រឹប​ផ្ទាំង​រូបភាព"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ko/strings.xml b/WallpaperPicker/res/values-ko/strings.xml
new file mode 100644
index 0000000..a5a85b7
--- /dev/null
+++ b/WallpaperPicker/res/values-ko/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"배경화면 설정"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"이미지를 로드할 수 없습니다."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"이미지를 배경화면으로 로드할 수 없습니다."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d개 선택됨"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d개 선택됨"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d개 선택됨"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"배경화면 %1$d/%2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> 선택함"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"삭제"</string>
+    <string name="pick_image" msgid="6704438906027442697">"이미지 선택"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"배경화면"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"배경화면 잘라내기"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-lo-rLA/strings.xml b/WallpaperPicker/res/values-lo-rLA/strings.xml
new file mode 100644
index 0000000..e468591
--- /dev/null
+++ b/WallpaperPicker/res/values-lo-rLA/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"ຕັ້ງເປັນພາບພື້ນຫຼັງ"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"ບໍ່ສາມາດໂຫຼດຮູບໄດ້"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"ບໍ່ສາມາດໂຫຼດຮູບເປັນພາບພື້ນຫຼັງໄດ້"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"ເລືອກ %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"ເລືອກ %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"ເລືອກ %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ພາບພື້ນຫຼັງ %1$d ໃນ %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"ເລືອກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"ລຶບ"</string>
+    <string name="pick_image" msgid="6704438906027442697">"ເລືອກ​ຮູບ​ພາບ"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"ພາບພື້ນຫຼັງ"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"ຕັດພາບພື້ນຫຼັງ"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-lt/strings.xml b/WallpaperPicker/res/values-lt/strings.xml
new file mode 100644
index 0000000..86035b8
--- /dev/null
+++ b/WallpaperPicker/res/values-lt/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Nustatyti ekrano foną"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Nepavyko įkelti vaizdo"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Nepavyko įkelti vaizdo kaip ekrano fono"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Pasirinkta: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Pasirinkta: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Pasirinkta: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d ekrano fonas iš %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Pasirinkta: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Ištrinti"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pasirinkti vaizdą"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Ekrano fonai"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Apkirpti ekrano foną"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-lv/strings.xml b/WallpaperPicker/res/values-lv/strings.xml
new file mode 100644
index 0000000..02e5cfb
--- /dev/null
+++ b/WallpaperPicker/res/values-lv/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Iestatīt fona tapeti"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Nevarēja ielādēt attēlu."</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Nevarēja ielādēt attēlu kā fona tapeti."</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Atlasīts: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Atlasīta: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Atlasītas: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. fona tapete no %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Atlasīta: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Dzēst"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Izvēlēties attēlu"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Fona tapetes"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Apgriezt fona tapeti"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-mn-rMN/strings.xml b/WallpaperPicker/res/values-mn-rMN/strings.xml
new file mode 100644
index 0000000..71ff9e0
--- /dev/null
+++ b/WallpaperPicker/res/values-mn-rMN/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Ханын зургийг тохируулах"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Зургийг ачаалж чадсангүй"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Зургийг ханын зураг болгож ачаалж чадсангүй"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d сонгогдсон"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d сонгогдсон"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d сонгогдсон"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d ханын цаасны %1$d нь"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> сонгогдсон"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Устгах"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Зураг сонгох"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Ханын зураг"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Ханын зургийг тайрах"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ms-rMY/strings.xml b/WallpaperPicker/res/values-ms-rMY/strings.xml
new file mode 100644
index 0000000..950f4d0
--- /dev/null
+++ b/WallpaperPicker/res/values-ms-rMY/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Tetapkan kertas dinding"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Tidak dapat memuatkan imej"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Tidak dapat memuatkan imej sebagai kertas dinding"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d dipilih"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d dipilih"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d dipilih"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Kertas dinding %1$d daripada %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Memilih <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Padam"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pilih imej"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Kertas dinding"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas kertas dinding"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-nb/strings.xml b/WallpaperPicker/res/values-nb/strings.xml
new file mode 100644
index 0000000..3589e4b
--- /dev/null
+++ b/WallpaperPicker/res/values-nb/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Angi bakgrunn"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Kunne ikke laste inn bildet"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Kunne ikke laste inn bildet som bakgrunn"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d valgt"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d valgt"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d valgt"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Bakgrunn %1$d av %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Valgt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Slett"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Velg bilde"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunner"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Beskjær bakgrunnen"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-nl/strings.xml b/WallpaperPicker/res/values-nl/strings.xml
new file mode 100644
index 0000000..7dd4f22
--- /dev/null
+++ b/WallpaperPicker/res/values-nl/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Achtergrond instellen"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Kan afbeelding niet laden"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Kan afbeelding niet laden als achtergrond"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d geselecteerd"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d geselecteerd"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d geselecteerd"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Achtergrond %1$d van %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> is geselecteerd"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Verwijderen"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Afbeelding kiezen"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Achtergronden"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Achtergrond bijsnijden"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-pl/strings.xml b/WallpaperPicker/res/values-pl/strings.xml
new file mode 100644
index 0000000..bcdbb3d
--- /dev/null
+++ b/WallpaperPicker/res/values-pl/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Ustaw tapetę"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Nie udało się załadować obrazu"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Nie udało się załadować obrazu jako tapety"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Wybranych %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Wybrana %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Wybrane: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Wybrano <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Usuń"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Wybierz obraz"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Przytnij tapetę"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-pt-rPT/strings.xml b/WallpaperPicker/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..8349232
--- /dev/null
+++ b/WallpaperPicker/res/values-pt-rPT/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Definir imagem fundo"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Não foi possível carregar a imagem"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Não foi possível carregar a imagem como imagem de fundo"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selecionadas"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selecionada"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selecionadas"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Imagem de fundo %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> selecionada"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Escolher imagem"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Imagens de fundo"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar imagem de fundo"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-pt/strings.xml b/WallpaperPicker/res/values-pt/strings.xml
new file mode 100644
index 0000000..2332fcb
--- /dev/null
+++ b/WallpaperPicker/res/values-pt/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Definir plano de fundo"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Não foi possível carregar a imagem"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Não foi possível carregar a imagem como plano de fundo"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selecionados"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selecionado"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selecionados"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Plano de fundo %1$d de %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> selecionado"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Excluir"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Escolher imagem"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Planos de fundo"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Cortar plano de fundo"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ro/strings.xml b/WallpaperPicker/res/values-ro/strings.xml
new file mode 100644
index 0000000..8ee1a5a
--- /dev/null
+++ b/WallpaperPicker/res/values-ro/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Setați imaginea de fundal"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Nu s-a putut încărca imaginea"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Nu s-a putut încărca imaginea ca fundal"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d selectate"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d selectată"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d selectate"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Imaginea de fundal %1$d din %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"S-a selectat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Ștergeți"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Alegeți imaginea"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Imagini de fundal"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Decupați imaginea de fundal"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-ru/strings.xml b/WallpaperPicker/res/values-ru/strings.xml
new file mode 100644
index 0000000..ff43ce8
--- /dev/null
+++ b/WallpaperPicker/res/values-ru/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Установить как обои"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Не удалось загрузить изображение"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Не удалось загрузить изображение"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Выбрано: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Выбрано: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Выбрано: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Обои %1$d из %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Выбран элемент \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Удалить"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Выбрать обои"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Обои"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Кадрировать обои"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sk/strings.xml b/WallpaperPicker/res/values-sk/strings.xml
new file mode 100644
index 0000000..33477a1
--- /dev/null
+++ b/WallpaperPicker/res/values-sk/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Nastaviť tapetu"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Obrázok nie je možné načítať"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Obrázok nie je možné načítať ako tapetu"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Počet vybratých položiek: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Počet vybratých položiek: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Počet vybratých položiek: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Vybratá položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Odstrániť"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Vybrať obrázok"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Orezanie tapety"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sl/strings.xml b/WallpaperPicker/res/values-sl/strings.xml
new file mode 100644
index 0000000..06a508a
--- /dev/null
+++ b/WallpaperPicker/res/values-sl/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Nastavi ozadje"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Slike ni bilo mogoče naložiti"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Slike ni bilo mogoče naložiti kot ozadje"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Št. izbranih: %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Št. izbranih: %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Št. izbranih: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. ozadje od %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Izbrano: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Izberi sliko"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Ozadja"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Obrezovanje ozadja"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sr/strings.xml b/WallpaperPicker/res/values-sr/strings.xml
new file mode 100644
index 0000000..fdfaaf6
--- /dev/null
+++ b/WallpaperPicker/res/values-sr/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Подеси позадину"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Није могуће учитати слику"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Није могуће учитати слику као позадину"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Изабрано је %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Изабрана је %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Изабраних: %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Позадина %1$d од %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Изабрана је <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Избриши"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Изабери слику"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Позадине"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Опсеци позадину"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sv/strings.xml b/WallpaperPicker/res/values-sv/strings.xml
new file mode 100644
index 0000000..57db3a6
--- /dev/null
+++ b/WallpaperPicker/res/values-sv/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Ange bakgrund"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Det gick inte att läsa in bilden"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Det gick inte att läsa in bilden som bakgrund"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d har valts"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d har valts"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d har valts"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Bakgrund %1$d av %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> har valts"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Ta bort"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Välj bild"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunder"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Beskär bakgrund"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sw/strings.xml b/WallpaperPicker/res/values-sw/strings.xml
new file mode 100644
index 0000000..edea3de
--- /dev/null
+++ b/WallpaperPicker/res/values-sw/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Weka mandhari"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Haikuweza kupakia picha"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Haikuweza kupakia picha iwe mandhari"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d zimechaguliwa"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d zimechaguliwa"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d zimechaguliwa"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Mandhari %1$d ya %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> iliyochaguliwa"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Futa"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Chagua picha"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Mandhari"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Punguza mandhari"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-sw720dp-v19/styles.xml b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
new file mode 100644
index 0000000..9107851
--- /dev/null
+++ b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+    <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
+        <item name="android:windowActionModeOverlay">true</item>
+        <item name="android:windowTranslucentStatus">true</item>
+        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+</resources>
diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml
index 9107851..b489090 100644
--- a/WallpaperPicker/res/values-sw720dp/styles.xml
+++ b/WallpaperPicker/res/values-sw720dp/styles.xml
@@ -20,7 +20,5 @@
 <resources>
     <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
         <item name="android:windowActionModeOverlay">true</item>
-        <item name="android:windowTranslucentStatus">true</item>
-        <item name="android:windowTranslucentNavigation">true</item>
     </style>
 </resources>
diff --git a/WallpaperPicker/res/values-th/strings.xml b/WallpaperPicker/res/values-th/strings.xml
new file mode 100644
index 0000000..6b4c235
--- /dev/null
+++ b/WallpaperPicker/res/values-th/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"ตั้งวอลเปเปอร์"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"ไม่สามารถโหลดรูปภาพ"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"ไม่สามารถโหลดรูปภาพเป็นวอลเปเปอร์"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"เลือกไว้ %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"เลือกไว้ %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"เลือกไว้ %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"วอลเปเปอร์ %1$d จาก %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"เลือก <xliff:g id="LABEL">%1$s</xliff:g> แล้ว"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"ลบ"</string>
+    <string name="pick_image" msgid="6704438906027442697">"เลือกรูปภาพ"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"วอลเปเปอร์"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"ครอบตัดวอลเปเปอร์"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-tl/strings.xml b/WallpaperPicker/res/values-tl/strings.xml
new file mode 100644
index 0000000..c9fe338
--- /dev/null
+++ b/WallpaperPicker/res/values-tl/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Itakda ang wallpaper"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Hindi ma-load ang larawan"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Hindi ma-load ang larawan bilang wallpaper"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d ang napili"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d ang napili"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d ang napili"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d ng %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Napili ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Tanggalin"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Pumili ng larawan"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Mga Wallpaper"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"I-crop ang wallpaper"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-tr/strings.xml b/WallpaperPicker/res/values-tr/strings.xml
new file mode 100644
index 0000000..3d03c6b
--- /dev/null
+++ b/WallpaperPicker/res/values-tr/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Duvar kağıdını ayarla"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Resim yüklenemedi"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Resim duvar kağıdı olarak yüklenemedi"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d tane seçildi"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d tane seçildi"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d tane seçildi"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d duvar kağıdı arasından duvar kağıdı %1$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seçildi"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Sil"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Resim seç"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Duvar kağıtları"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Duvar kağıdını kırp"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-uk/strings.xml b/WallpaperPicker/res/values-uk/strings.xml
new file mode 100644
index 0000000..076c882
--- /dev/null
+++ b/WallpaperPicker/res/values-uk/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Установити фон"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Не вдалося завантажити зображення"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Не вдалося завантажити зображення як фоновий малюнок"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Вибрано %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Вибрано %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Вибрано %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Фоновий малюнок %1$d з %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Вибрано <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Видалити"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Вибрати зображення"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Фонові малюнки"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Обрізати фоновий малюнок"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-v19/styles.xml b/WallpaperPicker/res/values-v19/styles.xml
new file mode 100644
index 0000000..85a989d
--- /dev/null
+++ b/WallpaperPicker/res/values-v19/styles.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+    <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
+        <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:windowActionBarOverlay">true</item>
+        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+
+    <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+        <item name="android:windowTranslucentStatus">true</item>
+        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+</resources>
diff --git a/WallpaperPicker/res/values-vi/strings.xml b/WallpaperPicker/res/values-vi/strings.xml
new file mode 100644
index 0000000..d1efbe9
--- /dev/null
+++ b/WallpaperPicker/res/values-vi/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Đặt hình nền"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Không thể tải hình ảnh"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Không thể tải hình ảnh làm hình nền"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"Đã chọn %1$d"</item>
+    <item quantity="one" msgid="8409622005831789373">"Đã chọn %1$d"</item>
+    <item quantity="other" msgid="479468347731745357">"Đã chọn %1$d"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Hình nền %1$d / %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> được chọn"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Xóa"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Chọn hình ảnh"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Hình nền"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Cắt hình nền"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-zh-rCN/strings.xml b/WallpaperPicker/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..1def9ed
--- /dev/null
+++ b/WallpaperPicker/res/values-zh-rCN/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"设置壁纸"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"无法加载图片"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"无法加载要设为壁纸的图片"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"已选择%1$d项"</item>
+    <item quantity="one" msgid="8409622005831789373">"已选择%1$d项"</item>
+    <item quantity="other" msgid="479468347731745357">"已选择%1$d项"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第%1$d张壁纸,共%2$d张"</string>
+    <string name="announce_selection" msgid="123723511662250539">"已选择<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"删除"</string>
+    <string name="pick_image" msgid="6704438906027442697">"选择图片"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"壁纸"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"剪裁壁纸"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-zh-rHK/strings.xml b/WallpaperPicker/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..66ba0af
--- /dev/null
+++ b/WallpaperPicker/res/values-zh-rHK/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"設定桌布"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"無法載入圖片"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"無法載入圖片設為桌布"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"已選取 %1$d 張"</item>
+    <item quantity="one" msgid="8409622005831789373">"已選取 %1$d 張"</item>
+    <item quantity="other" msgid="479468347731745357">"已選取 %1$d 張"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第 %1$d 張桌布,共 %2$d 張"</string>
+    <string name="announce_selection" msgid="123723511662250539">"已選取<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"刪除"</string>
+    <string name="pick_image" msgid="6704438906027442697">"選擇圖片"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-zh-rTW/strings.xml b/WallpaperPicker/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..4184976
--- /dev/null
+++ b/WallpaperPicker/res/values-zh-rTW/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"設定桌布"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"無法載入圖片"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"無法載入您要設為桌布的圖片"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"已選取 %1$d 個"</item>
+    <item quantity="one" msgid="8409622005831789373">"已選取 %1$d 個"</item>
+    <item quantity="other" msgid="479468347731745357">"已選取 %1$d 個"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第 %1$d 張桌布,共 %2$d 張"</string>
+    <string name="announce_selection" msgid="123723511662250539">"已選取<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"刪除"</string>
+    <string name="pick_image" msgid="6704438906027442697">"選擇圖片"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
+</resources>
diff --git a/WallpaperPicker/res/values-zu/strings.xml b/WallpaperPicker/res/values-zu/strings.xml
new file mode 100644
index 0000000..c7d3f33
--- /dev/null
+++ b/WallpaperPicker/res/values-zu/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="wallpaper_instructions" msgid="3524143401182707094">"Setha isithombe sangemuva"</string>
+    <string name="image_load_fail" msgid="7538534580694411837">"Ayikwazanga ukulayisha isithombe"</string>
+    <string name="wallpaper_load_fail" msgid="4800700444605404650">"Ayikwazanga ukulayisha isithombe njengesithombe sangemuva"</string>
+  <plurals name="number_of_items_selected">
+    <item quantity="zero" msgid="9015111147509924344">"%1$d khethiwe"</item>
+    <item quantity="one" msgid="8409622005831789373">"%1$d khethiwe"</item>
+    <item quantity="other" msgid="479468347731745357">"%1$d khethiwe"</item>
+  </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Isithombe sangemuva esingu-%1$d kwezingu-%2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhethiwe"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Susa"</string>
+    <string name="pick_image" msgid="6704438906027442697">"Khetha isithombe"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Izithombe zangemuva"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Nqampuna isithombe sangemuva"</string>
+</resources>
diff --git a/WallpaperPicker/res/values/config.xml b/WallpaperPicker/res/values/config.xml
index 1b24190..71580b5 100644
--- a/WallpaperPicker/res/values/config.xml
+++ b/WallpaperPicker/res/values/config.xml
@@ -15,4 +15,7 @@
 -->
 <resources>
     <bool name="allow_rotation">false</bool>
+    <!-- Specifies whether to expand the cropped area on both sides (rather
+         than just to one side) -->
+    <bool name="center_crop">false</bool>
 </resources>
diff --git a/WallpaperPicker/res/values/styles.xml b/WallpaperPicker/res/values/styles.xml
index 0e48dda..16b11f2 100644
--- a/WallpaperPicker/res/values/styles.xml
+++ b/WallpaperPicker/res/values/styles.xml
@@ -22,7 +22,12 @@
         <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
         <item name="android:windowFullscreen">true</item>
         <item name="android:windowActionBarOverlay">true</item>
-        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+
+    <style name="Theme.WallpaperPicker" parent="Theme.WallpaperCropper">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowShowWallpaper">true</item>
     </style>
 
     <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
@@ -31,7 +36,9 @@
     </style>
 
     <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
-        <item name="android:windowTranslucentStatus">true</item>
-        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+
+    <style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.Holo.ActionButton">
+        <item name="android:textColor">#ffffffff</item>
     </style>
 </resources>
diff --git a/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java
new file mode 100644
index 0000000..f0796c3
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Button;
+
+/**
+ * A Button which becomes translucent when it is disabled
+ */
+public class AlphaDisableableButton extends Button {
+    public static float DISABLED_ALPHA_VALUE = 0.4f;
+    public AlphaDisableableButton(Context context) {
+        this(context, null);
+    }
+
+    public AlphaDisableableButton(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public AlphaDisableableButton(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        if(enabled) {
+            setAlpha(1.0f);
+        } else {
+            setAlpha(DISABLED_ALPHA_VALUE);
+        }
+    }
+}
diff --git a/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
index 60b2537..88f4461 100644
--- a/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
@@ -122,7 +122,7 @@
             Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
             preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
                     mInfo.getComponent());
-            a.onLiveWallpaperPickerLaunch();
+            a.onLiveWallpaperPickerLaunch(mInfo);
             a.startActivityForResultSafely(preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
         }
     }
diff --git a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index 58add70..2bdf8f1 100644
--- a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
+++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
@@ -34,8 +34,6 @@
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
-import com.android.photos.BitmapRegionTileSource;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -49,42 +47,23 @@
     Context mContext;
     LayoutInflater mLayoutInflater;
 
-    public static class SavedWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo {
+    public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
         private int mDbId;
-        private Drawable mThumb;
-        public SavedWallpaperTile(int dbId, Drawable thumb) {
+        public SavedWallpaperTile(int dbId, File target, Drawable thumb) {
+            super(target, thumb);
             mDbId = dbId;
-            mThumb = thumb;
         }
-        @Override
-        public void onClick(WallpaperPickerActivity a) {
-            String imageFilename = a.getSavedImages().getImageFilename(mDbId);
-            File file = new File(a.getFilesDir(), imageFilename);
-            BitmapRegionTileSource.FilePathBitmapSource bitmapSource =
-                    new BitmapRegionTileSource.FilePathBitmapSource(file.getAbsolutePath(), 1024);
-            a.setCropViewTileSource(bitmapSource, false, true, null);
-        }
-        @Override
-        public void onSave(WallpaperPickerActivity a) {
-            boolean finishActivityWhenDone = true;
-            String imageFilename = a.getSavedImages().getImageFilename(mDbId);
-            a.setWallpaper(imageFilename, finishActivityWhenDone);
-        }
+
         @Override
         public void onDelete(WallpaperPickerActivity a) {
             a.getSavedImages().deleteImage(mDbId);
         }
-        @Override
-        public boolean isSelectable() {
-            return true;
-        }
-        @Override
-        public boolean isNamelessWallpaper() {
-            return true;
-        }
     }
 
     public SavedWallpaperImages(Activity context) {
+        // We used to store the saved images in the cache directory, but that meant they'd get
+        // deleted sometimes-- move them to the data directory
+        ImageDb.moveFromCacheDirectoryIfNecessary(context);
         mDb = new ImageDb(context);
         mContext = context;
         mLayoutInflater = context.getLayoutInflater();
@@ -95,7 +74,8 @@
         SQLiteDatabase db = mDb.getReadableDatabase();
         Cursor result = db.query(ImageDb.TABLE_NAME,
                 new String[] { ImageDb.COLUMN_ID,
-                    ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME }, // cols to return
+                    ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
+                    ImageDb.COLUMN_IMAGE_FILENAME}, // cols to return
                 null, // select query
                 null, // args to select query
                 null,
@@ -109,7 +89,9 @@
 
             Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
             if (thumb != null) {
-                mImages.add(new SavedWallpaperTile(result.getInt(0), new BitmapDrawable(thumb)));
+                mImages.add(new SavedWallpaperTile(result.getInt(0),
+                        new File(mContext.getFilesDir(), result.getString(2)),
+                        new BitmapDrawable(thumb)));
             }
         }
         result.close();
@@ -133,15 +115,7 @@
             Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
         }
         return WallpaperPickerActivity.createImageTileView(
-                mLayoutInflater, position, convertView, parent, thumbDrawable);
-    }
-
-    public String getImageFilename(int id) {
-        Pair<String, String> filenames = getImageFilenames(id);
-        if (filenames != null) {
-            return filenames.second;
-        }
-        return null;
+                mLayoutInflater, convertView, parent, thumbDrawable);
     }
 
     private Pair<String, String> getImageFilenames(int id) {
@@ -215,11 +189,20 @@
         Context mContext;
 
         public ImageDb(Context context) {
-            super(context, new File(context.getCacheDir(), DB_NAME).getPath(), null, DB_VERSION);
+            super(context, context.getDatabasePath(DB_NAME).getPath(), null, DB_VERSION);
             // Store the context for later use
             mContext = context;
         }
 
+        public static void moveFromCacheDirectoryIfNecessary(Context context) {
+            // We used to store the saved images in the cache directory, but that meant they'd get
+            // deleted sometimes-- move them to the data directory
+            File oldSavedImagesFile = new File(context.getCacheDir(), ImageDb.DB_NAME);
+            File savedImagesFile = context.getDatabasePath(ImageDb.DB_NAME);
+            if (oldSavedImagesFile.exists()) {
+                oldSavedImagesFile.renameTo(savedImagesFile);
+            }
+        }
         @Override
         public void onCreate(SQLiteDatabase database) {
             database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index b3ef073..d5c7cd9 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -75,6 +75,7 @@
 
     protected CropView mCropView;
     protected Uri mUri;
+    protected View mSetWallpaperButton;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -111,10 +112,12 @@
                         cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone);
                     }
                 });
+        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
 
         // Load image in background
         final BitmapRegionTileSource.UriBitmapSource bitmapSource =
                 new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
+        mSetWallpaperButton.setEnabled(false);
         Runnable onLoad = new Runnable() {
             public void run() {
                 if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
@@ -122,12 +125,22 @@
                             getString(R.string.wallpaper_load_fail),
                             Toast.LENGTH_LONG).show();
                     finish();
+                } else {
+                    mSetWallpaperButton.setEnabled(true);
                 }
             }
         };
         setCropViewTileSource(bitmapSource, true, false, onLoad);
     }
 
+    @Override
+    protected void onDestroy() {
+        if (mCropView != null) {
+            mCropView.destroy();
+        }
+        super.onDestroy();
+    }
+
     public void setCropViewTileSource(
             final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
             final boolean moveToLeft, final Runnable postExecute) {
@@ -136,7 +149,21 @@
         final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
             protected Void doInBackground(Void...args) {
                 if (!isCancelled()) {
-                    bitmapSource.loadInBackground();
+                    try {
+                        bitmapSource.loadInBackground();
+                    } catch (SecurityException securityException) {
+                        if (isDestroyed()) {
+                            // Temporarily granted permissions are revoked when the activity
+                            // finishes, potentially resulting in a SecurityException here.
+                            // Even though {@link #isDestroyed} might also return true in different
+                            // situations where the configuration changes, we are fine with
+                            // catching these cases here as well.
+                            cancel(false);
+                        } else {
+                            // otherwise it had a different cause and we throw it further
+                            throw securityException;
+                        }
+                    }
                 }
                 return null;
             }
@@ -271,6 +298,9 @@
             }
         } catch (IOException e) {
             Log.w(LOGTAG, "Getting exif data failed", e);
+        } catch (NullPointerException e) {
+            // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid
+            Log.w(LOGTAG, "Getting exif data failed", e);
         } finally {
             Utils.closeSilently(bis);
             Utils.closeSilently(is);
@@ -278,10 +308,10 @@
         return 0;
     }
 
-    protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) {
-        int rotation = getRotationFromExif(filePath);
+    protected void setWallpaper(Uri uri, final boolean finishActivityWhenDone) {
+        int rotation = getRotationFromExif(this, uri);
         BitmapCropTask cropTask = new BitmapCropTask(
-                this, filePath, null, rotation, 0, 0, true, false, null);
+                this, uri, null, rotation, 0, 0, true, false, null);
         final Point bounds = cropTask.getImageBounds();
         Runnable onEndCrop = new Runnable() {
             public void run() {
@@ -330,10 +360,10 @@
 
     protected void cropImageAndSetWallpaper(Uri uri,
             OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
+        boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
         // Get the crop
         boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
 
-
         Display d = getWindowManager().getDefaultDisplay();
 
         Point displaySize = new Point();
@@ -344,10 +374,13 @@
                 getWindowManager());
         // Get the crop
         RectF cropRect = mCropView.getCrop();
+
+        Point inSize = mCropView.getSourceDimensions();
+
         int cropRotation = mCropView.getImageRotation();
         float cropScale = mCropView.getWidth() / (float) cropRect.width();
 
-        Point inSize = mCropView.getSourceDimensions();
+
         Matrix rotateMatrix = new Matrix();
         rotateMatrix.setRotate(cropRotation);
         float[] rotatedInSize = new float[] { inSize.x, inSize.y };
@@ -355,18 +388,36 @@
         rotatedInSize[0] = Math.abs(rotatedInSize[0]);
         rotatedInSize[1] = Math.abs(rotatedInSize[1]);
 
+
+        // due to rounding errors in the cropview renderer the edges can be slightly offset
+        // therefore we ensure that the boundaries are sanely defined
+        cropRect.left = Math.max(0, cropRect.left);
+        cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
+        cropRect.top = Math.max(0, cropRect.top);
+        cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
+
         // ADJUST CROP WIDTH
         // Extend the crop all the way to the right, for parallax
         // (or all the way to the left, in RTL)
-        float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
+        float extraSpace;
+        if (centerCrop) {
+            extraSpace = 2f * Math.min(rotatedInSize[0] - cropRect.right, cropRect.left);
+        } else {
+            extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
+        }
         // Cap the amount of extra width
         float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
         extraSpace = Math.min(extraSpace, maxExtraSpace);
 
-        if (ltr) {
-            cropRect.right += extraSpace;
+        if (centerCrop) {
+            cropRect.left -= extraSpace / 2f;
+            cropRect.right += extraSpace / 2f;
         } else {
-            cropRect.left -= extraSpace;
+            if (ltr) {
+                cropRect.right += extraSpace;
+            } else {
+                cropRect.left -= extraSpace;
+            }
         }
 
         // ADJUST CROP HEIGHT
@@ -781,17 +832,28 @@
         editor.commit();
 
         suggestWallpaperDimension(getResources(),
-                sp, getWindowManager(), WallpaperManager.getInstance(this));
+                sp, getWindowManager(), WallpaperManager.getInstance(this), true);
     }
 
     static public void suggestWallpaperDimension(Resources res,
             final SharedPreferences sharedPrefs,
             WindowManager windowManager,
-            final WallpaperManager wallpaperManager) {
+            final WallpaperManager wallpaperManager, boolean fallBackToDefaults) {
         final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager);
         // If we have saved a wallpaper width/height, use that instead
-        int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x);
-        int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y);
+
+        int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, -1);
+        int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, -1);
+
+        if (savedWidth == -1 || savedHeight == -1) {
+            if (!fallBackToDefaults) {
+                return;
+            } else {
+                savedWidth = defaultWallpaperSize.x;
+                savedHeight = defaultWallpaperSize.y;
+            }
+        }
+
         if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
                 savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
             wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index d3c779f..0728537 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -16,8 +16,8 @@
 
 package com.android.launcher3;
 
-import android.animation.Animator;
 import android.animation.LayoutTransition;
+import android.annotation.TargetApi;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.WallpaperInfo;
@@ -33,7 +33,6 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -60,14 +59,15 @@
 import android.view.ViewPropertyAnimator;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.WindowManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+import android.widget.ArrayAdapter;
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.ListAdapter;
 import android.widget.Toast;
 
 import com.android.photos.BitmapRegionTileSource;
@@ -85,8 +85,10 @@
     public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
     public static final int PICK_LIVE_WALLPAPER = 7;
     private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
+    private static final String SELECTED_INDEX = "SELECTED_INDEX";
     private static final String OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb.jpg";
     private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb2.jpg";
+    private static final int FLAG_POST_DELAY_MILLIS = 200;
 
     private View mSelectedTile;
     private boolean mIgnoreNextTap;
@@ -103,9 +105,13 @@
     ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>();
     private SavedWallpaperImages mSavedImages;
     private WallpaperInfo mLiveWallpaperInfoOnPickerLaunch;
+    private int mSelectedIndex = -1;
+    private WallpaperInfo mLastClickedLiveWallpaperInfo;
 
     public static abstract class WallpaperTileInfo {
         protected View mView;
+        public Drawable mThumb;
+
         public void setView(View v) {
             mView = v;
         }
@@ -144,12 +150,13 @@
                 onLoad = null;
             } else {
                 mFirstClick = false;
+                a.mSetWallpaperButton.setEnabled(false);
                 onLoad = new Runnable() {
                     public void run() {
                         if (mBitmapSource != null &&
                                 mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
-                            mView.setVisibility(View.VISIBLE);
                             a.selectTile(mView);
+                            a.mSetWallpaperButton.setEnabled(true);
                         } else {
                             ViewGroup parent = (ViewGroup) mView.getParent();
                             if (parent != null) {
@@ -190,10 +197,36 @@
         }
     }
 
+    public static class FileWallpaperInfo extends WallpaperTileInfo {
+        private File mFile;
+
+        public FileWallpaperInfo(File target, Drawable thumb) {
+            mFile = target;
+            mThumb = thumb;
+        }
+        @Override
+        public void onClick(WallpaperPickerActivity a) {
+            BitmapRegionTileSource.UriBitmapSource bitmapSource =
+                    new BitmapRegionTileSource.UriBitmapSource(a, Uri.fromFile(mFile), 1024);
+            a.setCropViewTileSource(bitmapSource, false, true, null);
+        }
+        @Override
+        public void onSave(WallpaperPickerActivity a) {
+            a.setWallpaper(Uri.fromFile(mFile), true);
+        }
+        @Override
+        public boolean isSelectable() {
+            return true;
+        }
+        @Override
+        public boolean isNamelessWallpaper() {
+            return true;
+        }
+    }
+
     public static class ResourceWallpaperInfo extends WallpaperTileInfo {
         private Resources mResources;
         private int mResId;
-        private Drawable mThumb;
 
         public ResourceWallpaperInfo(Resources res, int resId, Drawable thumb) {
             mResources = res;
@@ -216,6 +249,7 @@
                     wallpaperSize.x, wallpaperSize.y, false);
             v.setScale(wallpaperSize.x / crop.width());
             v.setTouchEnabled(false);
+            a.setSystemWallpaperVisiblity(false);
         }
         @Override
         public void onSave(WallpaperPickerActivity a) {
@@ -232,8 +266,8 @@
         }
     }
 
+    @TargetApi(Build.VERSION_CODES.KITKAT)
     public static class DefaultWallpaperInfo extends WallpaperTileInfo {
-        public Drawable mThumb;
         public DefaultWallpaperInfo(Drawable thumb) {
             mThumb = thumb;
         }
@@ -244,15 +278,23 @@
             Drawable defaultWallpaper = WallpaperManager.getInstance(a).getBuiltInDrawable(
                     c.getWidth(), c.getHeight(), false, 0.5f, 0.5f);
 
+            if (defaultWallpaper == null) {
+                Log.w(TAG, "Null default wallpaper encountered.");
+                c.setTileSource(null, null);
+                return;
+            }
+
             c.setTileSource(
                     new DrawableTileSource(a, defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE), null);
             c.setScale(1f);
             c.setTouchEnabled(false);
+            a.setSystemWallpaperVisiblity(false);
         }
         @Override
         public void onSave(WallpaperPickerActivity a) {
             try {
                 WallpaperManager.getInstance(a).clear();
+                a.setResult(RESULT_OK);
             } catch (IOException e) {
                 Log.w("Setting wallpaper to default threw exception", e);
             }
@@ -272,11 +314,70 @@
         mWallpaperStrip.setPadding(0, 0, 0, (int) offset);
     }
 
+    /**
+     * shows the system wallpaper behind the window and hides the {@link
+     * #mCropView} if visible
+     * @param visible should the system wallpaper be shown
+     */
+    protected void setSystemWallpaperVisiblity(final boolean visible) {
+        // hide our own wallpaper preview if necessary
+        if(!visible) {
+            mCropView.setVisibility(View.VISIBLE);
+        } else {
+            changeWallpaperFlags(visible);
+        }
+        // the change of the flag must be delayed in order to avoid flickering,
+        // a simple post / double post does not suffice here
+        mCropView.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                if(!visible) {
+                    changeWallpaperFlags(visible);
+                } else {
+                    mCropView.setVisibility(View.INVISIBLE);
+                }
+            }
+        }, FLAG_POST_DELAY_MILLIS);
+    }
+
+    private void changeWallpaperFlags(boolean visible) {
+        int desiredWallpaperFlag = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
+        int currentWallpaperFlag = getWindow().getAttributes().flags
+                & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        if (desiredWallpaperFlag != currentWallpaperFlag) {
+            getWindow().setFlags(desiredWallpaperFlag,
+                    WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
+        }
+    }
+
+    @Override
+    public void setCropViewTileSource(BitmapSource bitmapSource,
+                                      boolean touchEnabled,
+                                      boolean moveToLeft,
+                                      final Runnable postExecute) {
+        // we also want to show our own wallpaper instead of the one in the background
+        Runnable showPostExecuteRunnable = new Runnable() {
+            @Override
+            public void run() {
+                if(postExecute != null) {
+                    postExecute.run();
+                }
+                setSystemWallpaperVisiblity(false);
+            }
+        };
+        super.setCropViewTileSource(bitmapSource,
+                touchEnabled,
+                moveToLeft,
+                showPostExecuteRunnable);
+    }
+
     // called by onCreate; this is subclassed to overwrite WallpaperCropActivity
     protected void init() {
         setContentView(R.layout.wallpaper_picker);
 
         mCropView = (CropView) findViewById(R.id.cropView);
+        mCropView.setVisibility(View.INVISIBLE);
+
         mWallpaperStrip = findViewById(R.id.wallpaper_strip);
         mCropView.setTouchCallback(new CropView.TouchCallback() {
             ViewPropertyAnimator mAnim;
@@ -330,6 +431,7 @@
                     }
                     return;
                 }
+                mSetWallpaperButton.setEnabled(true);
                 WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
                 if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
                     selectTile(v);
@@ -358,9 +460,9 @@
         };
 
         // Populate the built-in wallpapers
-        ArrayList<ResourceWallpaperInfo> wallpapers = findBundledWallpapers();
+        ArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();
         mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
-        BuiltInWallpapersAdapter ia = new BuiltInWallpapersAdapter(this, wallpapers);
+        SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(this, wallpapers);
         populateWallpapersFromAdapter(mWallpapersView, ia, false);
 
         // Populate the saved wallpapers
@@ -411,18 +513,6 @@
         pickImageInfo.setView(pickImageTile);
         pickImageTile.setOnClickListener(mThumbnailOnClickListener);
 
-        // Add a tile for the default wallpaper
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            DefaultWallpaperInfo defaultWallpaperInfo = getDefaultWallpaper();
-            FrameLayout defaultWallpaperTile = (FrameLayout) createImageTileView(
-                    getLayoutInflater(), 0, null, mWallpapersView, defaultWallpaperInfo.mThumb);
-            setWallpaperItemPaddingToZero(defaultWallpaperTile);
-            defaultWallpaperTile.setTag(defaultWallpaperInfo);
-            mWallpapersView.addView(defaultWallpaperTile, 0);
-            defaultWallpaperTile.setOnClickListener(mThumbnailOnClickListener);
-            defaultWallpaperInfo.setView(defaultWallpaperTile);
-        }
-
         // Select the first item; wait for a layout pass so that we initialize the dimensions of
         // cropView or the defaultWallpaperView first
         mCropView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -430,8 +520,10 @@
             public void onLayoutChange(View v, int left, int top, int right, int bottom,
                     int oldLeft, int oldTop, int oldRight, int oldBottom) {
                 if ((right - left) > 0 && (bottom - top) > 0) {
-                    if (mWallpapersView.getChildCount() > 0) {
-                        mThumbnailOnClickListener.onClick(mWallpapersView.getChildAt(0));
+                    if (mSelectedIndex >= 0 && mSelectedIndex < mWallpapersView.getChildCount()) {
+                        mThumbnailOnClickListener.onClick(
+                                mWallpapersView.getChildAt(mSelectedIndex));
+                        setSystemWallpaperVisiblity(false);
                     }
                     v.removeOnLayoutChangeListener(this);
                 }
@@ -461,9 +553,14 @@
                         if (mSelectedTile != null) {
                             WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
                             info.onSave(WallpaperPickerActivity.this);
+                        } else {
+                            // no tile was selected, so we just finish the activity and go back
+                            setResult(Activity.RESULT_OK);
+                            finish();
                         }
                     }
                 });
+        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
 
         // CAB for deleting items
         mActionModeCallback = new ActionMode.Callback() {
@@ -510,6 +607,7 @@
                 if (itemId == R.id.menu_delete) {
                     int childCount = mWallpapersView.getChildCount();
                     ArrayList<View> viewsToRemove = new ArrayList<View>();
+                    boolean selectedTileRemoved = false;
                     for (int i = 0; i < childCount; i++) {
                         CheckableFrameLayout c =
                                 (CheckableFrameLayout) mWallpapersView.getChildAt(i);
@@ -517,11 +615,19 @@
                             WallpaperTileInfo info = (WallpaperTileInfo) c.getTag();
                             info.onDelete(WallpaperPickerActivity.this);
                             viewsToRemove.add(c);
+                            if (i == mSelectedIndex) {
+                                selectedTileRemoved = true;
+                            }
                         }
                     }
                     for (View v : viewsToRemove) {
                         mWallpapersView.removeView(v);
                     }
+                    if (selectedTileRemoved) {
+                        mSelectedIndex = -1;
+                        mSelectedTile = null;
+                        setSystemWallpaperVisiblity(true);
+                    }
                     updateTileIndices();
                     mode.finish(); // Action picked, so close the CAB
                     return true;
@@ -538,7 +644,9 @@
                     CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
                     c.setChecked(false);
                 }
-                mSelectedTile.setSelected(true);
+                if (mSelectedTile != null) {
+                    mSelectedTile.setSelected(true);
+                }
                 mActionMode = null;
             }
         };
@@ -551,6 +659,7 @@
         }
         mSelectedTile = v;
         v.setSelected(true);
+        mSelectedIndex = mWallpapersView.indexOfChild(v);
         // TODO: Remove this once the accessibility framework and
         // services have better support for selection state.
         v.announceForAccessibility(
@@ -580,13 +689,16 @@
                 new String[] { MediaStore.Images.ImageColumns._ID,
                     MediaStore.Images.ImageColumns.DATE_TAKEN},
                 null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC LIMIT 1");
+
         Bitmap thumb = null;
-        if (cursor.moveToNext()) {
-            int id = cursor.getInt(0);
-            thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
-                    id, MediaStore.Images.Thumbnails.MINI_KIND, null);
+        if (cursor != null) {
+            if (cursor.moveToNext()) {
+                int id = cursor.getInt(0);
+                thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
+                        id, MediaStore.Images.Thumbnails.MINI_KIND, null);
+            }
+            cursor.close();
         }
-        cursor.close();
         return thumb;
     }
 
@@ -601,13 +713,15 @@
 
     protected void onSaveInstanceState(Bundle outState) {
         outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles);
+        outState.putInt(SELECTED_INDEX, mSelectedIndex);
     }
 
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
         ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES);
         for (Uri uri : uris) {
-            addTemporaryWallpaperTile(uri);
+            addTemporaryWallpaperTile(uri, true);
         }
+        mSelectedIndex = savedInstanceState.getInt(SELECTED_INDEX, -1);
     }
 
     private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
@@ -711,7 +825,7 @@
         }
     }
 
-    private void addTemporaryWallpaperTile(final Uri uri) {
+    private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) {
         mTempWallpaperTiles.add(uri);
         // Add a tile for the image picked from Gallery
         final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
@@ -726,15 +840,30 @@
         final Context context = this;
         new AsyncTask<Void, Bitmap, Bitmap>() {
             protected Bitmap doInBackground(Void...args) {
-                int rotation = WallpaperCropActivity.getRotationFromExif(context, uri);
-                return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
-
+                try {
+                    int rotation = WallpaperCropActivity.getRotationFromExif(context, uri);
+                    return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
+                } catch (SecurityException securityException) {
+                    if (isDestroyed()) {
+                        // Temporarily granted permissions are revoked when the activity
+                        // finishes, potentially resulting in a SecurityException here.
+                        // Even though {@link #isDestroyed} might also return true in different
+                        // situations where the configuration changes, we are fine with
+                        // catching these cases here as well.
+                        cancel(false);
+                    } else {
+                        // otherwise it had a different cause and we throw it further
+                        throw securityException;
+                    }
+                    return null;
+                }
             }
             protected void onPostExecute(Bitmap thumb) {
-                if (thumb != null) {
+                if (!isCancelled() && thumb != null) {
                     image.setImageBitmap(thumb);
                     Drawable thumbDrawable = image.getDrawable();
                     thumbDrawable.setDither(true);
+                    pickedImageThumbnail.setVisibility(View.VISIBLE);
                 } else {
                     Log.e(TAG, "Error loading thumbnail for uri=" + uri);
                 }
@@ -747,14 +876,16 @@
         addLongPressHandler(pickedImageThumbnail);
         updateTileIndices();
         pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener);
-        mThumbnailOnClickListener.onClick(pickedImageThumbnail);
+        if (!fromRestore) {
+            mThumbnailOnClickListener.onClick(pickedImageThumbnail);
+        }
     }
 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) {
             if (data != null && data.getData() != null) {
                 Uri uri = data.getData();
-                addTemporaryWallpaperTile(uri);
+                addTemporaryWallpaperTile(uri, false);
             }
         } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) {
             setResult(RESULT_OK);
@@ -762,11 +893,15 @@
         } else if (requestCode == PICK_LIVE_WALLPAPER) {
             WallpaperManager wm = WallpaperManager.getInstance(this);
             final WallpaperInfo oldLiveWallpaper = mLiveWallpaperInfoOnPickerLaunch;
+            final WallpaperInfo clickedWallpaper = mLastClickedLiveWallpaperInfo;
             WallpaperInfo newLiveWallpaper = wm.getWallpaperInfo();
             // Try to figure out if a live wallpaper was set;
             if (newLiveWallpaper != null &&
-                    (oldLiveWallpaper == null ||
-                    !oldLiveWallpaper.getComponent().equals(newLiveWallpaper.getComponent()))) {
+                    (oldLiveWallpaper == null
+                            || !oldLiveWallpaper.getComponent()
+                                    .equals(newLiveWallpaper.getComponent())
+                            || clickedWallpaper.getComponent()
+                                    .equals(oldLiveWallpaper.getComponent()))) {
                 // Return if a live wallpaper was set
                 setResult(RESULT_OK);
                 finish();
@@ -783,27 +918,68 @@
         v.setOnLongClickListener(mLongClickListener);
     }
 
-    private ArrayList<ResourceWallpaperInfo> findBundledWallpapers() {
-        ArrayList<ResourceWallpaperInfo> bundledWallpapers =
-                new ArrayList<ResourceWallpaperInfo>(24);
+    private ArrayList<WallpaperTileInfo> findBundledWallpapers() {
+        final PackageManager pm = getPackageManager();
+        final ArrayList<WallpaperTileInfo> bundled = new ArrayList<WallpaperTileInfo>(24);
+
+        Partner partner = Partner.get(pm);
+        if (partner != null) {
+            final Resources partnerRes = partner.getResources();
+            final int resId = partnerRes.getIdentifier(Partner.RES_WALLPAPERS, "array",
+                    partner.getPackageName());
+            if (resId != 0) {
+                addWallpapers(bundled, partnerRes, partner.getPackageName(), resId);
+            }
+
+            // Add system wallpapers
+            File systemDir = partner.getWallpaperDirectory();
+            if (systemDir != null && systemDir.isDirectory()) {
+                for (File file : systemDir.listFiles()) {
+                    if (!file.isFile()) {
+                        continue;
+                    }
+                    String name = file.getName();
+                    int dotPos = name.lastIndexOf('.');
+                    String extension = "";
+                    if (dotPos >= -1) {
+                        extension = name.substring(dotPos);
+                        name = name.substring(0, dotPos);
+                    }
+
+                    if (name.endsWith("_small")) {
+                        // it is a thumbnail
+                        continue;
+                    }
+
+                    File thumbnail = new File(systemDir, name + "_small" + extension);
+                    Bitmap thumb = BitmapFactory.decodeFile(thumbnail.getAbsolutePath());
+                    if (thumb != null) {
+                        bundled.add(new FileWallpaperInfo(file, new BitmapDrawable(thumb)));
+                    }
+                }
+            }
+        }
 
         Pair<ApplicationInfo, Integer> r = getWallpaperArrayResourceId();
         if (r != null) {
             try {
                 Resources wallpaperRes = getPackageManager().getResourcesForApplication(r.first);
-                bundledWallpapers = addWallpapers(wallpaperRes, r.first.packageName, r.second);
+                addWallpapers(bundled, wallpaperRes, r.first.packageName, r.second);
             } catch (PackageManager.NameNotFoundException e) {
             }
         }
 
-        // Add an entry for the default wallpaper (stored in system resources)
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
-            ResourceWallpaperInfo defaultWallpaperInfo = getPreKKDefaultWallpaperInfo();
+        if (partner == null || !partner.hideDefaultWallpaper()) {
+            // Add an entry for the default wallpaper (stored in system resources)
+            WallpaperTileInfo defaultWallpaperInfo =
+                    (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
+                    ? getPreKKDefaultWallpaperInfo()
+                    : getDefaultWallpaper();
             if (defaultWallpaperInfo != null) {
-                bundledWallpapers.add(0, defaultWallpaperInfo);
+                bundled.add(0, defaultWallpaperInfo);
             }
         }
-        return bundledWallpapers;
+        return bundled;
     }
 
     private boolean writeImageToFileAsJpeg(File f, Bitmap b) {
@@ -821,11 +997,27 @@
         return false;
     }
 
+    private File getDefaultThumbFile() {
+        return new File(getFilesDir(), Build.VERSION.SDK_INT
+                + "_" + DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
+    }
+
+    private boolean saveDefaultWallpaperThumb(Bitmap b) {
+        // Delete old thumbnails.
+        new File(getFilesDir(), OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+        new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+
+        for (int i = Build.VERSION_CODES.JELLY_BEAN; i < Build.VERSION.SDK_INT; i++) {
+            new File(getFilesDir(), i + "_" + DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+        }
+        return writeImageToFileAsJpeg(getDefaultThumbFile(), b);
+    }
+
     private ResourceWallpaperInfo getPreKKDefaultWallpaperInfo() {
         Resources sysRes = Resources.getSystem();
         int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android");
 
-        File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
+        File defaultThumbFile = getDefaultThumbFile();
         Bitmap thumb = null;
         boolean defaultWallpaperExists = false;
         if (defaultThumbFile.exists()) {
@@ -838,7 +1030,7 @@
             thumb = createThumbnail(
                     defaultThumbSize, this, null, null, sysRes, resId, rotation, false);
             if (thumb != null) {
-                defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb);
+                defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
             }
         }
         if (defaultWallpaperExists) {
@@ -847,18 +1039,15 @@
         return null;
     }
 
+    @TargetApi(Build.VERSION_CODES.KITKAT)
     private DefaultWallpaperInfo getDefaultWallpaper() {
-        File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
+        File defaultThumbFile = getDefaultThumbFile();
         Bitmap thumb = null;
         boolean defaultWallpaperExists = false;
         if (defaultThumbFile.exists()) {
             thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
             defaultWallpaperExists = true;
         } else {
-            // Delete old thumbnail file, since we had a bug where the thumbnail wasn't being drawn
-            // before
-            new File(getFilesDir(), OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
-
             Resources res = getResources();
             Point defaultThumbSize = getDefaultThumbnailSize(res);
             Drawable wallpaperDrawable = WallpaperManager.getInstance(this).getBuiltInDrawable(
@@ -872,7 +1061,7 @@
                 c.setBitmap(null);
             }
             if (thumb != null) {
-                defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb);
+                defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
             }
         }
         if (defaultWallpaperExists) {
@@ -895,10 +1084,8 @@
         }
     }
 
-    private ArrayList<ResourceWallpaperInfo> addWallpapers(
-            Resources res, String packageName, int listResId) {
-        ArrayList<ResourceWallpaperInfo> bundledWallpapers =
-                new ArrayList<ResourceWallpaperInfo>(24);
+    private void addWallpapers(ArrayList<WallpaperTileInfo> known, Resources res,
+            String packageName, int listResId) {
         final String[] extras = res.getStringArray(listResId);
         for (String extra : extras) {
             int resId = res.getIdentifier(extra, "drawable", packageName);
@@ -908,14 +1095,13 @@
                 if (thumbRes != 0) {
                     ResourceWallpaperInfo wallpaperInfo =
                             new ResourceWallpaperInfo(res, resId, res.getDrawable(thumbRes));
-                    bundledWallpapers.add(wallpaperInfo);
+                    known.add(wallpaperInfo);
                     // Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");
                 }
             } else {
                 Log.e(TAG, "Couldn't find wallpaper " + extra);
             }
         }
-        return bundledWallpapers;
     }
 
     public CropView getCropView() {
@@ -926,7 +1112,8 @@
         return mSavedImages;
     }
 
-    public void onLiveWallpaperPickerLaunch() {
+    public void onLiveWallpaperPickerLaunch(WallpaperInfo info) {
+        mLastClickedLiveWallpaperInfo = info;
         mLiveWallpaperInfoOnPickerLaunch = WallpaperManager.getInstance(this).getWallpaperInfo();
     }
 
@@ -944,37 +1131,24 @@
         }
     }
 
-    private static class BuiltInWallpapersAdapter extends BaseAdapter implements ListAdapter {
-        private LayoutInflater mLayoutInflater;
-        private ArrayList<ResourceWallpaperInfo> mWallpapers;
+    private static class SimpleWallpapersAdapter extends ArrayAdapter<WallpaperTileInfo> {
+        private final LayoutInflater mLayoutInflater;
 
-        BuiltInWallpapersAdapter(Activity activity, ArrayList<ResourceWallpaperInfo> wallpapers) {
+        SimpleWallpapersAdapter(Activity activity, ArrayList<WallpaperTileInfo> wallpapers) {
+            super(activity, R.layout.wallpaper_picker_item, wallpapers);
             mLayoutInflater = activity.getLayoutInflater();
-            mWallpapers = wallpapers;
-        }
-
-        public int getCount() {
-            return mWallpapers.size();
-        }
-
-        public ResourceWallpaperInfo getItem(int position) {
-            return mWallpapers.get(position);
-        }
-
-        public long getItemId(int position) {
-            return position;
         }
 
         public View getView(int position, View convertView, ViewGroup parent) {
-            Drawable thumb = mWallpapers.get(position).mThumb;
+            Drawable thumb = getItem(position).mThumb;
             if (thumb == null) {
                 Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
             }
-            return createImageTileView(mLayoutInflater, position, convertView, parent, thumb);
+            return createImageTileView(mLayoutInflater, convertView, parent, thumb);
         }
     }
 
-    public static View createImageTileView(LayoutInflater layoutInflater, int position,
+    public static View createImageTileView(LayoutInflater layoutInflater,
             View convertView, ViewGroup parent, Drawable thumb) {
         View view;
 
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index cdc5cdc..66ece4f 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -245,6 +245,9 @@
             try {
                 ei.readExif(mPath);
                 return true;
+            } catch (NullPointerException e) {
+                Log.w("BitmapRegionTileSource", "reading exif failed", e);
+                return false;
             } catch (IOException e) {
                 Log.w("BitmapRegionTileSource", "getting decoder failed", e);
                 return false;
@@ -280,9 +283,6 @@
             } catch (FileNotFoundException e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
                 return null;
-            } catch (IOException e) {
-                Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e);
-                return null;
             }
         }
         @Override
@@ -311,6 +311,9 @@
             } catch (IOException e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
                 return false;
+            } catch (NullPointerException e) {
+                Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e);
+                return false;
             } finally {
                 Utils.closeSilently(is);
             }
diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
index af4199c..94063b0 100644
--- a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
@@ -112,6 +112,18 @@
         //setTileSource(new ColoredTiles());
     }
 
+    @Override
+    public void setVisibility(int visibility) {
+        super.setVisibility(visibility);
+        // need to update inner view's visibility because it seems like we're causing it to draw
+        // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible.
+        if (USE_TEXTURE_VIEW) {
+            mTextureView.setVisibility(visibility);
+        } else {
+            mGLSurfaceView.setVisibility(visibility);
+        }
+    }
+
     public void destroy() {
         if (!IS_SUPPORTED) {
             return;
diff --git a/proguard.flags b/proguard.flags
index a922e91..0b28c0e 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -52,3 +52,8 @@
 -keep class com.android.launcher3.MemoryDumpActivity {
   *;
 }
+
+-keep class com.android.launcher3.PreloadIconDrawable {
+  public float getAnimationProgress();
+  public void setAnimationProgress(float);
+}
diff --git a/res/values-sw340dp-port/dimens.xml b/res/anim/no_anim.xml
similarity index 79%
rename from res/values-sw340dp-port/dimens.xml
rename to res/anim/no_anim.xml
index e360565..02b1625 100644
--- a/res/values-sw340dp-port/dimens.xml
+++ b/res/anim/no_anim.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +14,5 @@
      limitations under the License.
 -->
 
-<resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">70dp</dimen>
-</resources>
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="417" />
diff --git a/res/anim/task_open_enter.xml b/res/anim/task_open_enter.xml
new file mode 100644
index 0000000..3eb1915
--- /dev/null
+++ b/res/anim/task_open_enter.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+    <alpha android:fromAlpha="0" android:toAlpha="1.0"
+            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@interpolator/decelerate_quart"
+            android:startOffset="0"
+            android:duration="167"/>
+
+    <translate android:fromYDelta="110%" android:toYDelta="0"
+            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:startOffset="0"
+            android:duration="417" />
+</set>
diff --git a/res/drawable-hdpi/bg_cling1.png b/res/drawable-hdpi/bg_cling1.png
deleted file mode 100644
index 0e15532..0000000
--- a/res/drawable-hdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/bg_cling2.png b/res/drawable-hdpi/bg_cling2.png
deleted file mode 100644
index e65d9a2..0000000
--- a/res/drawable-hdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/bg_cling3.png b/res/drawable-hdpi/bg_cling3.png
deleted file mode 100644
index ea71fbd..0000000
--- a/res/drawable-hdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/bg_cling4.png b/res/drawable-hdpi/bg_cling4.png
deleted file mode 100644
index 9403667..0000000
--- a/res/drawable-hdpi/bg_cling4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling.9.png b/res/drawable-hdpi/cling.9.png
deleted file mode 100644
index 36fbfc8..0000000
--- a/res/drawable-hdpi/cling.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_arrow_down.png b/res/drawable-hdpi/cling_arrow_down.png
deleted file mode 100644
index 4f521ea..0000000
--- a/res/drawable-hdpi/cling_arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_arrow_left.png b/res/drawable-hdpi/cling_arrow_left.png
deleted file mode 100644
index 13764c9..0000000
--- a/res/drawable-hdpi/cling_arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_arrow_right.png b/res/drawable-hdpi/cling_arrow_right.png
deleted file mode 100644
index be52244..0000000
--- a/res/drawable-hdpi/cling_arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_arrow_up.png b/res/drawable-hdpi/cling_arrow_up.png
deleted file mode 100644
index 83b5b37..0000000
--- a/res/drawable-hdpi/cling_arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_bg.9.png b/res/drawable-hdpi/cling_bg.9.png
new file mode 100644
index 0000000..e173ba5
--- /dev/null
+++ b/res/drawable-hdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/cling_button.9.png b/res/drawable-hdpi/cling_button.9.png
deleted file mode 100644
index e308382..0000000
--- a/res/drawable-hdpi/cling_button.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/cling_button_pressed.9.png b/res/drawable-hdpi/cling_button_pressed.9.png
deleted file mode 100644
index 4f9ca6f..0000000
--- a/res/drawable-hdpi/cling_button_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/custom_content_page.png b/res/drawable-hdpi/custom_content_page.png
deleted file mode 100644
index 9eef50c..0000000
--- a/res/drawable-hdpi/custom_content_page.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/focused_bg.9.png b/res/drawable-hdpi/focused_bg.9.png
deleted file mode 100644
index 2925ae8..0000000
--- a/res/drawable-hdpi/focused_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_allapps.png b/res/drawable-hdpi/ic_allapps.png
index e7677d5..b98e65f 100644
--- a/res/drawable-hdpi/ic_allapps.png
+++ b/res/drawable-hdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_allapps_pressed.png b/res/drawable-hdpi/ic_allapps_pressed.png
index 863eeba..b7eaa67 100644
--- a/res/drawable-hdpi/ic_allapps_pressed.png
+++ b/res/drawable-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_add.png b/res/drawable-hdpi/ic_pageindicator_add.png
index c37d622..ab0e5db 100644
--- a/res/drawable-hdpi/ic_pageindicator_add.png
+++ b/res/drawable-hdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_current.png b/res/drawable-hdpi/ic_pageindicator_current.png
index aac8d40..2e841f5 100644
--- a/res/drawable-hdpi/ic_pageindicator_current.png
+++ b/res/drawable-hdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_default.png b/res/drawable-hdpi/ic_pageindicator_default.png
index bafd94b..07ab948 100644
--- a/res/drawable-hdpi/ic_pageindicator_default.png
+++ b/res/drawable-hdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting.png b/res/drawable-hdpi/ic_setting.png
index 3f5bc43..1c12a5b 100644
--- a/res/drawable-hdpi/ic_setting.png
+++ b/res/drawable-hdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting_pressed.png b/res/drawable-hdpi/ic_setting_pressed.png
index 9201064..d5b5ca2 100644
--- a/res/drawable-hdpi/ic_setting_pressed.png
+++ b/res/drawable-hdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_wallpaper.png b/res/drawable-hdpi/ic_wallpaper.png
index 5e5d118..34d5943 100644
--- a/res/drawable-hdpi/ic_wallpaper.png
+++ b/res/drawable-hdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_wallpaper_pressed.png b/res/drawable-hdpi/ic_wallpaper_pressed.png
index d104e57..1588ce7 100644
--- a/res/drawable-hdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-hdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget.png b/res/drawable-hdpi/ic_widget.png
index 8c57af0..ed7e1ca 100644
--- a/res/drawable-hdpi/ic_widget.png
+++ b/res/drawable-hdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_pressed.png b/res/drawable-hdpi/ic_widget_pressed.png
index 081f9f9..19d6fed 100644
--- a/res/drawable-hdpi/ic_widget_pressed.png
+++ b/res/drawable-hdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left.9.png b/res/drawable-hdpi/page_hover_left.9.png
new file mode 100644
index 0000000..cc029d8
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left_active.9.png b/res/drawable-hdpi/page_hover_left_active.9.png
new file mode 100644
index 0000000..20c91a0
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left_holo.9.png b/res/drawable-hdpi/page_hover_left_holo.9.png
deleted file mode 100644
index 8a1aa5f..0000000
--- a/res/drawable-hdpi/page_hover_left_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right.9.png b/res/drawable-hdpi/page_hover_right.9.png
new file mode 100644
index 0000000..a42822a
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right_active.9.png b/res/drawable-hdpi/page_hover_right_active.9.png
new file mode 100644
index 0000000..523fafd
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right_holo.9.png b/res/drawable-hdpi/page_hover_right_holo.9.png
deleted file mode 100644
index abf8f51..0000000
--- a/res/drawable-hdpi/page_hover_right_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel.9.png b/res/drawable-hdpi/quantum_panel.9.png
new file mode 100644
index 0000000..b4ac9c0
--- /dev/null
+++ b/res/drawable-hdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_dark.9.png b/res/drawable-hdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..abaf230
--- /dev/null
+++ b/res/drawable-hdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/screenpanel.9.png b/res/drawable-hdpi/screenpanel.9.png
index 36e7dfd..f7ae011 100644
--- a/res/drawable-hdpi/screenpanel.9.png
+++ b/res/drawable-hdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-hdpi/screenpanel_hover.9.png b/res/drawable-hdpi/screenpanel_hover.9.png
index 3321fc9..ac8e83d 100644
--- a/res/drawable-hdpi/screenpanel_hover.9.png
+++ b/res/drawable-hdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-hdpi/virtual_preload.9.png b/res/drawable-hdpi/virtual_preload.9.png
new file mode 100644
index 0000000..71e5326
--- /dev/null
+++ b/res/drawable-hdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-hdpi/virtual_preload_folder.9.png b/res/drawable-hdpi/virtual_preload_folder.9.png
new file mode 100644
index 0000000..ece3226
--- /dev/null
+++ b/res/drawable-hdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_container_holo.9.png b/res/drawable-hdpi/widget_container_holo.9.png
deleted file mode 100644
index 8c15a7c..0000000
--- a/res/drawable-hdpi/widget_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-hdpi/bg_cling1.png b/res/drawable-land-hdpi/bg_cling1.png
deleted file mode 100644
index 7123c5c..0000000
--- a/res/drawable-land-hdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-hdpi/bg_cling2.png b/res/drawable-land-hdpi/bg_cling2.png
deleted file mode 100644
index 889b627..0000000
--- a/res/drawable-land-hdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-hdpi/bg_cling3.png b/res/drawable-land-hdpi/bg_cling3.png
deleted file mode 100644
index 4ff338c..0000000
--- a/res/drawable-land-hdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-mdpi/bg_cling1.png b/res/drawable-land-mdpi/bg_cling1.png
deleted file mode 100644
index f5faeb4..0000000
--- a/res/drawable-land-mdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-mdpi/bg_cling2.png b/res/drawable-land-mdpi/bg_cling2.png
deleted file mode 100644
index 963967d..0000000
--- a/res/drawable-land-mdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-mdpi/bg_cling3.png b/res/drawable-land-mdpi/bg_cling3.png
deleted file mode 100644
index 921831a..0000000
--- a/res/drawable-land-mdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xhdpi/bg_cling1.png b/res/drawable-land-xhdpi/bg_cling1.png
deleted file mode 100644
index 2282117..0000000
--- a/res/drawable-land-xhdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xhdpi/bg_cling2.png b/res/drawable-land-xhdpi/bg_cling2.png
deleted file mode 100644
index 5243889..0000000
--- a/res/drawable-land-xhdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xhdpi/bg_cling3.png b/res/drawable-land-xhdpi/bg_cling3.png
deleted file mode 100644
index 08475f7..0000000
--- a/res/drawable-land-xhdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xxhdpi/bg_cling1.png b/res/drawable-land-xxhdpi/bg_cling1.png
deleted file mode 100644
index 78943f0..0000000
--- a/res/drawable-land-xxhdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xxhdpi/bg_cling2.png b/res/drawable-land-xxhdpi/bg_cling2.png
deleted file mode 100644
index 98b6568..0000000
--- a/res/drawable-land-xxhdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-land-xxhdpi/bg_cling3.png b/res/drawable-land-xxhdpi/bg_cling3.png
deleted file mode 100644
index e249fe5..0000000
--- a/res/drawable-land-xxhdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_cling1.png b/res/drawable-mdpi/bg_cling1.png
deleted file mode 100644
index f284412..0000000
--- a/res/drawable-mdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_cling2.png b/res/drawable-mdpi/bg_cling2.png
deleted file mode 100644
index 0052dc2..0000000
--- a/res/drawable-mdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_cling3.png b/res/drawable-mdpi/bg_cling3.png
deleted file mode 100644
index fabdf7a..0000000
--- a/res/drawable-mdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_cling4.png b/res/drawable-mdpi/bg_cling4.png
deleted file mode 100644
index 2f152f4d..0000000
--- a/res/drawable-mdpi/bg_cling4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_cling5.png b/res/drawable-mdpi/bg_cling5.png
deleted file mode 100644
index e094809..0000000
--- a/res/drawable-mdpi/bg_cling5.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling.9.png b/res/drawable-mdpi/cling.9.png
deleted file mode 100644
index 4c0f139..0000000
--- a/res/drawable-mdpi/cling.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_arrow_down.png b/res/drawable-mdpi/cling_arrow_down.png
deleted file mode 100644
index 58e66fb..0000000
--- a/res/drawable-mdpi/cling_arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_arrow_left.png b/res/drawable-mdpi/cling_arrow_left.png
deleted file mode 100644
index 023c717..0000000
--- a/res/drawable-mdpi/cling_arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_arrow_right.png b/res/drawable-mdpi/cling_arrow_right.png
deleted file mode 100644
index cf0eb10..0000000
--- a/res/drawable-mdpi/cling_arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_arrow_up.png b/res/drawable-mdpi/cling_arrow_up.png
deleted file mode 100644
index 9b0e6b7..0000000
--- a/res/drawable-mdpi/cling_arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_bg.9.png b/res/drawable-mdpi/cling_bg.9.png
new file mode 100644
index 0000000..fc49c89
--- /dev/null
+++ b/res/drawable-mdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/cling_button.9.png b/res/drawable-mdpi/cling_button.9.png
deleted file mode 100644
index a0b6f97..0000000
--- a/res/drawable-mdpi/cling_button.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/cling_button_pressed.9.png b/res/drawable-mdpi/cling_button_pressed.9.png
deleted file mode 100644
index 986e669..0000000
--- a/res/drawable-mdpi/cling_button_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/custom_content_page.png b/res/drawable-mdpi/custom_content_page.png
deleted file mode 100644
index cc4005d..0000000
--- a/res/drawable-mdpi/custom_content_page.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/focused_bg.9.png b/res/drawable-mdpi/focused_bg.9.png
deleted file mode 100644
index 89c29ac..0000000
--- a/res/drawable-mdpi/focused_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps.png b/res/drawable-mdpi/ic_allapps.png
index e0fd9c0..f410673 100644
--- a/res/drawable-mdpi/ic_allapps.png
+++ b/res/drawable-mdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps_pressed.png b/res/drawable-mdpi/ic_allapps_pressed.png
index 3bd87b1..aa4f913 100644
--- a/res/drawable-mdpi/ic_allapps_pressed.png
+++ b/res/drawable-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_add.png b/res/drawable-mdpi/ic_pageindicator_add.png
index 8e05e64..11659a3 100644
--- a/res/drawable-mdpi/ic_pageindicator_add.png
+++ b/res/drawable-mdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_current.png b/res/drawable-mdpi/ic_pageindicator_current.png
index ab5f4c8..08f43b4 100644
--- a/res/drawable-mdpi/ic_pageindicator_current.png
+++ b/res/drawable-mdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_default.png b/res/drawable-mdpi/ic_pageindicator_default.png
index c919ee8..635be4a 100644
--- a/res/drawable-mdpi/ic_pageindicator_default.png
+++ b/res/drawable-mdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting.png b/res/drawable-mdpi/ic_setting.png
index 1e76459..c614e91 100644
--- a/res/drawable-mdpi/ic_setting.png
+++ b/res/drawable-mdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting_pressed.png b/res/drawable-mdpi/ic_setting_pressed.png
index d7aca18..61e574a 100644
--- a/res/drawable-mdpi/ic_setting_pressed.png
+++ b/res/drawable-mdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_wallpaper.png b/res/drawable-mdpi/ic_wallpaper.png
index 333a206..8f2a00a 100644
--- a/res/drawable-mdpi/ic_wallpaper.png
+++ b/res/drawable-mdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_wallpaper_pressed.png b/res/drawable-mdpi/ic_wallpaper_pressed.png
index 273c48b..aa598c3 100644
--- a/res/drawable-mdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-mdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget.png b/res/drawable-mdpi/ic_widget.png
index 5f974c2..1bd3935 100644
--- a/res/drawable-mdpi/ic_widget.png
+++ b/res/drawable-mdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_pressed.png b/res/drawable-mdpi/ic_widget_pressed.png
index 0a3e883..9b690d9 100644
--- a/res/drawable-mdpi/ic_widget_pressed.png
+++ b/res/drawable-mdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_left.9.png b/res/drawable-mdpi/page_hover_left.9.png
new file mode 100644
index 0000000..2bbf428
--- /dev/null
+++ b/res/drawable-mdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_left_active.9.png b/res/drawable-mdpi/page_hover_left_active.9.png
new file mode 100644
index 0000000..bf70f36
--- /dev/null
+++ b/res/drawable-mdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_left_holo.9.png b/res/drawable-mdpi/page_hover_left_holo.9.png
deleted file mode 100644
index 561d3cd..0000000
--- a/res/drawable-mdpi/page_hover_left_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_right.9.png b/res/drawable-mdpi/page_hover_right.9.png
new file mode 100644
index 0000000..4bafd0f
--- /dev/null
+++ b/res/drawable-mdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_right_active.9.png b/res/drawable-mdpi/page_hover_right_active.9.png
new file mode 100644
index 0000000..4aaa014
--- /dev/null
+++ b/res/drawable-mdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_right_holo.9.png b/res/drawable-mdpi/page_hover_right_holo.9.png
deleted file mode 100644
index 2681f23..0000000
--- a/res/drawable-mdpi/page_hover_right_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel.9.png b/res/drawable-mdpi/quantum_panel.9.png
new file mode 100644
index 0000000..c5a6eb7
--- /dev/null
+++ b/res/drawable-mdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_dark.9.png b/res/drawable-mdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..7728a72
--- /dev/null
+++ b/res/drawable-mdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/screenpanel.9.png b/res/drawable-mdpi/screenpanel.9.png
index 4de3017..c2779fc 100644
--- a/res/drawable-mdpi/screenpanel.9.png
+++ b/res/drawable-mdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-mdpi/screenpanel_hover.9.png b/res/drawable-mdpi/screenpanel_hover.9.png
index dd77406..70b3078 100644
--- a/res/drawable-mdpi/screenpanel_hover.9.png
+++ b/res/drawable-mdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-mdpi/virtual_preload.9.png b/res/drawable-mdpi/virtual_preload.9.png
new file mode 100644
index 0000000..a3c7519
--- /dev/null
+++ b/res/drawable-mdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-mdpi/virtual_preload_folder.9.png b/res/drawable-mdpi/virtual_preload_folder.9.png
new file mode 100644
index 0000000..fa2f131
--- /dev/null
+++ b/res/drawable-mdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_container_holo.9.png b/res/drawable-mdpi/widget_container_holo.9.png
deleted file mode 100644
index db24457..0000000
--- a/res/drawable-mdpi/widget_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-nodpi/ic_migration.png b/res/drawable-nodpi/ic_migration.png
new file mode 100644
index 0000000..c282cd2
--- /dev/null
+++ b/res/drawable-nodpi/ic_migration.png
Binary files differ
diff --git a/res/drawable-xhdpi/bg_cling1.png b/res/drawable-xhdpi/bg_cling1.png
deleted file mode 100644
index b71351a..0000000
--- a/res/drawable-xhdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_cling2.png b/res/drawable-xhdpi/bg_cling2.png
deleted file mode 100644
index ad78dfe..0000000
--- a/res/drawable-xhdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_cling3.png b/res/drawable-xhdpi/bg_cling3.png
deleted file mode 100644
index ae04195..0000000
--- a/res/drawable-xhdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_cling4.png b/res/drawable-xhdpi/bg_cling4.png
deleted file mode 100644
index f4bb83e..0000000
--- a/res/drawable-xhdpi/bg_cling4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling.9.png b/res/drawable-xhdpi/cling.9.png
deleted file mode 100644
index 1cb4681..0000000
--- a/res/drawable-xhdpi/cling.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_arrow_down.png b/res/drawable-xhdpi/cling_arrow_down.png
deleted file mode 100644
index ee10933..0000000
--- a/res/drawable-xhdpi/cling_arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_arrow_left.png b/res/drawable-xhdpi/cling_arrow_left.png
deleted file mode 100644
index cffbcf3..0000000
--- a/res/drawable-xhdpi/cling_arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_arrow_right.png b/res/drawable-xhdpi/cling_arrow_right.png
deleted file mode 100644
index d880d67..0000000
--- a/res/drawable-xhdpi/cling_arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_arrow_up.png b/res/drawable-xhdpi/cling_arrow_up.png
deleted file mode 100644
index fd2c60c..0000000
--- a/res/drawable-xhdpi/cling_arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_bg.9.png b/res/drawable-xhdpi/cling_bg.9.png
new file mode 100644
index 0000000..4db356f
--- /dev/null
+++ b/res/drawable-xhdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/cling_button.9.png b/res/drawable-xhdpi/cling_button.9.png
deleted file mode 100644
index 4192563..0000000
--- a/res/drawable-xhdpi/cling_button.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/cling_button_pressed.9.png b/res/drawable-xhdpi/cling_button_pressed.9.png
deleted file mode 100644
index d3ce469..0000000
--- a/res/drawable-xhdpi/cling_button_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/custom_content_page.png b/res/drawable-xhdpi/custom_content_page.png
deleted file mode 100644
index e1da91c..0000000
--- a/res/drawable-xhdpi/custom_content_page.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/focused_bg.9.png b/res/drawable-xhdpi/focused_bg.9.png
deleted file mode 100644
index 197a269..0000000
--- a/res/drawable-xhdpi/focused_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps.png b/res/drawable-xhdpi/ic_allapps.png
index f71964c..ff3d823 100644
--- a/res/drawable-xhdpi/ic_allapps.png
+++ b/res/drawable-xhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps_pressed.png b/res/drawable-xhdpi/ic_allapps_pressed.png
index d678f02..5f188f6 100644
--- a/res/drawable-xhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_add.png b/res/drawable-xhdpi/ic_pageindicator_add.png
index 28e164b..af1da2d 100644
--- a/res/drawable-xhdpi/ic_pageindicator_add.png
+++ b/res/drawable-xhdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_current.png b/res/drawable-xhdpi/ic_pageindicator_current.png
index aed3d71..0e9a52f 100644
--- a/res/drawable-xhdpi/ic_pageindicator_current.png
+++ b/res/drawable-xhdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_default.png b/res/drawable-xhdpi/ic_pageindicator_default.png
index 0887416..d0f14cd 100644
--- a/res/drawable-xhdpi/ic_pageindicator_default.png
+++ b/res/drawable-xhdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting.png b/res/drawable-xhdpi/ic_setting.png
index 6f06bcf..3a7310b 100644
--- a/res/drawable-xhdpi/ic_setting.png
+++ b/res/drawable-xhdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting_pressed.png b/res/drawable-xhdpi/ic_setting_pressed.png
index bca8ccd..005d49c 100644
--- a/res/drawable-xhdpi/ic_setting_pressed.png
+++ b/res/drawable-xhdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_wallpaper.png b/res/drawable-xhdpi/ic_wallpaper.png
index 41dc000..d2bf246 100644
--- a/res/drawable-xhdpi/ic_wallpaper.png
+++ b/res/drawable-xhdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_wallpaper_pressed.png b/res/drawable-xhdpi/ic_wallpaper_pressed.png
index ffff053..5a9b84d 100644
--- a/res/drawable-xhdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-xhdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget.png b/res/drawable-xhdpi/ic_widget.png
index 47dcdd1..cf6be81 100644
--- a/res/drawable-xhdpi/ic_widget.png
+++ b/res/drawable-xhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_pressed.png b/res/drawable-xhdpi/ic_widget_pressed.png
index 8bb387b..633c9c6 100644
--- a/res/drawable-xhdpi/ic_widget_pressed.png
+++ b/res/drawable-xhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_left.9.png b/res/drawable-xhdpi/page_hover_left.9.png
new file mode 100644
index 0000000..a2b9b65
--- /dev/null
+++ b/res/drawable-xhdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_left_active.9.png b/res/drawable-xhdpi/page_hover_left_active.9.png
new file mode 100644
index 0000000..ba9478e
--- /dev/null
+++ b/res/drawable-xhdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_left_holo.9.png b/res/drawable-xhdpi/page_hover_left_holo.9.png
deleted file mode 100644
index 4972a2e..0000000
--- a/res/drawable-xhdpi/page_hover_left_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_right.9.png b/res/drawable-xhdpi/page_hover_right.9.png
new file mode 100644
index 0000000..1243ea9
--- /dev/null
+++ b/res/drawable-xhdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_right_active.9.png b/res/drawable-xhdpi/page_hover_right_active.9.png
new file mode 100644
index 0000000..582261c
--- /dev/null
+++ b/res/drawable-xhdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_right_holo.9.png b/res/drawable-xhdpi/page_hover_right_holo.9.png
deleted file mode 100644
index b99461f..0000000
--- a/res/drawable-xhdpi/page_hover_right_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel.9.png b/res/drawable-xhdpi/quantum_panel.9.png
new file mode 100644
index 0000000..1797ad5
--- /dev/null
+++ b/res/drawable-xhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_dark.9.png b/res/drawable-xhdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..4c1868b
--- /dev/null
+++ b/res/drawable-xhdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/screenpanel.9.png b/res/drawable-xhdpi/screenpanel.9.png
index b4b828d..53a7812 100644
--- a/res/drawable-xhdpi/screenpanel.9.png
+++ b/res/drawable-xhdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/screenpanel_hover.9.png b/res/drawable-xhdpi/screenpanel_hover.9.png
index a44dc11..a2e200f 100644
--- a/res/drawable-xhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/virtual_preload.9.png b/res/drawable-xhdpi/virtual_preload.9.png
new file mode 100644
index 0000000..d2c3fea
--- /dev/null
+++ b/res/drawable-xhdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/virtual_preload_folder.9.png b/res/drawable-xhdpi/virtual_preload_folder.9.png
new file mode 100644
index 0000000..1f9202b
--- /dev/null
+++ b/res/drawable-xhdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_container_holo.9.png b/res/drawable-xhdpi/widget_container_holo.9.png
deleted file mode 100644
index 1313fe7..0000000
--- a/res/drawable-xhdpi/widget_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/apps_customize_bg.png b/res/drawable-xxhdpi/apps_customize_bg.png
new file mode 100644
index 0000000..a51cc11
--- /dev/null
+++ b/res/drawable-xxhdpi/apps_customize_bg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling1.png b/res/drawable-xxhdpi/bg_cling1.png
deleted file mode 100644
index 0777856..0000000
--- a/res/drawable-xxhdpi/bg_cling1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling2.png b/res/drawable-xxhdpi/bg_cling2.png
deleted file mode 100644
index 1797a1b..0000000
--- a/res/drawable-xxhdpi/bg_cling2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling3.png b/res/drawable-xxhdpi/bg_cling3.png
deleted file mode 100644
index a87be63..0000000
--- a/res/drawable-xxhdpi/bg_cling3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling4.png b/res/drawable-xxhdpi/bg_cling4.png
deleted file mode 100644
index cabe919..0000000
--- a/res/drawable-xxhdpi/bg_cling4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling_home.png b/res/drawable-xxhdpi/bg_cling_home.png
deleted file mode 100644
index 1ae93e7..0000000
--- a/res/drawable-xxhdpi/bg_cling_home.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_cling_nakasi3.png b/res/drawable-xxhdpi/bg_cling_nakasi3.png
deleted file mode 100644
index f47236c..0000000
--- a/res/drawable-xxhdpi/bg_cling_nakasi3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling.9.png b/res/drawable-xxhdpi/cling.9.png
deleted file mode 100644
index 7beae03..0000000
--- a/res/drawable-xxhdpi/cling.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_arrow_down.png b/res/drawable-xxhdpi/cling_arrow_down.png
deleted file mode 100644
index 48c4f06..0000000
--- a/res/drawable-xxhdpi/cling_arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_arrow_left.png b/res/drawable-xxhdpi/cling_arrow_left.png
deleted file mode 100644
index 8760d05..0000000
--- a/res/drawable-xxhdpi/cling_arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_arrow_right.png b/res/drawable-xxhdpi/cling_arrow_right.png
deleted file mode 100644
index 356ba17..0000000
--- a/res/drawable-xxhdpi/cling_arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_arrow_up.png b/res/drawable-xxhdpi/cling_arrow_up.png
deleted file mode 100644
index 4cb805f..0000000
--- a/res/drawable-xxhdpi/cling_arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_bg.9.png b/res/drawable-xxhdpi/cling_bg.9.png
new file mode 100644
index 0000000..dc9f69a
--- /dev/null
+++ b/res/drawable-xxhdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_button.9.png b/res/drawable-xxhdpi/cling_button.9.png
deleted file mode 100644
index e412876..0000000
--- a/res/drawable-xxhdpi/cling_button.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_button_pressed.9.png b/res/drawable-xxhdpi/cling_button_pressed.9.png
deleted file mode 100644
index 55e89da..0000000
--- a/res/drawable-xxhdpi/cling_button_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/focused_bg.9.png b/res/drawable-xxhdpi/focused_bg.9.png
deleted file mode 100644
index 84d3062..0000000
--- a/res/drawable-xxhdpi/focused_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps.png b/res/drawable-xxhdpi/ic_allapps.png
index 624e0ef..5dbfe4c 100644
--- a/res/drawable-xxhdpi/ic_allapps.png
+++ b/res/drawable-xxhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps_pressed.png b/res/drawable-xxhdpi/ic_allapps_pressed.png
index 77b45ae..e761723 100644
--- a/res/drawable-xxhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xxhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_add.png b/res/drawable-xxhdpi/ic_pageindicator_add.png
index fd8a662..c288952 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_add.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_current.png b/res/drawable-xxhdpi/ic_pageindicator_current.png
index 08615f3..b74e92e 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_current.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_default.png b/res/drawable-xxhdpi/ic_pageindicator_default.png
index 9d4fbf8..e362ece 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_default.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting.png b/res/drawable-xxhdpi/ic_setting.png
index b3729d3..01bdcd5 100644
--- a/res/drawable-xxhdpi/ic_setting.png
+++ b/res/drawable-xxhdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting_pressed.png b/res/drawable-xxhdpi/ic_setting_pressed.png
index 5c9c1be..d0cad5e 100644
--- a/res/drawable-xxhdpi/ic_setting_pressed.png
+++ b/res/drawable-xxhdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_wallpaper.png b/res/drawable-xxhdpi/ic_wallpaper.png
index c718444..490c45a 100644
--- a/res/drawable-xxhdpi/ic_wallpaper.png
+++ b/res/drawable-xxhdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_wallpaper_pressed.png b/res/drawable-xxhdpi/ic_wallpaper_pressed.png
index 03324aa..e5d200b 100644
--- a/res/drawable-xxhdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-xxhdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget.png b/res/drawable-xxhdpi/ic_widget.png
index fddfeca..d4b8324 100644
--- a/res/drawable-xxhdpi/ic_widget.png
+++ b/res/drawable-xxhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_pressed.png b/res/drawable-xxhdpi/ic_widget_pressed.png
index 3d3670e..b8dd35d 100644
--- a/res/drawable-xxhdpi/ic_widget_pressed.png
+++ b/res/drawable-xxhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_left.9.png b/res/drawable-xxhdpi/page_hover_left.9.png
new file mode 100644
index 0000000..63869dd
--- /dev/null
+++ b/res/drawable-xxhdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_left_active.9.png b/res/drawable-xxhdpi/page_hover_left_active.9.png
new file mode 100644
index 0000000..9a418ce
--- /dev/null
+++ b/res/drawable-xxhdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_left_holo.9.png b/res/drawable-xxhdpi/page_hover_left_holo.9.png
deleted file mode 100644
index 626aafb..0000000
--- a/res/drawable-xxhdpi/page_hover_left_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_right.9.png b/res/drawable-xxhdpi/page_hover_right.9.png
new file mode 100644
index 0000000..c6fd398
--- /dev/null
+++ b/res/drawable-xxhdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_right_active.9.png b/res/drawable-xxhdpi/page_hover_right_active.9.png
new file mode 100644
index 0000000..7aef373
--- /dev/null
+++ b/res/drawable-xxhdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_right_holo.9.png b/res/drawable-xxhdpi/page_hover_right_holo.9.png
deleted file mode 100644
index 66257dc..0000000
--- a/res/drawable-xxhdpi/page_hover_right_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel.9.png b/res/drawable-xxhdpi/quantum_panel.9.png
new file mode 100644
index 0000000..d7ba874
--- /dev/null
+++ b/res/drawable-xxhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_dark.9.png b/res/drawable-xxhdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..17ba0f1
--- /dev/null
+++ b/res/drawable-xxhdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/screenpanel.9.png b/res/drawable-xxhdpi/screenpanel.9.png
index c44f3b8..2d13954 100644
--- a/res/drawable-xxhdpi/screenpanel.9.png
+++ b/res/drawable-xxhdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/screenpanel_hover.9.png b/res/drawable-xxhdpi/screenpanel_hover.9.png
index 1ab18da..369fc44 100644
--- a/res/drawable-xxhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xxhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/virtual_preload.9.png b/res/drawable-xxhdpi/virtual_preload.9.png
new file mode 100644
index 0000000..93e3b33
--- /dev/null
+++ b/res/drawable-xxhdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/virtual_preload_folder.9.png b/res/drawable-xxhdpi/virtual_preload_folder.9.png
new file mode 100644
index 0000000..fae19b3
--- /dev/null
+++ b/res/drawable-xxhdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_container_holo.9.png b/res/drawable-xxhdpi/widget_container_holo.9.png
deleted file mode 100644
index 8f79920..0000000
--- a/res/drawable-xxhdpi/widget_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bg_migration_cling.xml b/res/drawable/bg_migration_cling.xml
new file mode 100644
index 0000000..bfff5a4
--- /dev/null
+++ b/res/drawable/bg_migration_cling.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval" >
+
+    <gradient
+        android:endColor="#00ffeb3a"
+        android:gradientRadius="50%p"
+        android:startColor="#80ffeb3a"
+        android:type="radial" />
+
+</shape>
\ No newline at end of file
diff --git a/res/drawable/cling_arrow_end.xml b/res/drawable/cling_arrow_end.xml
deleted file mode 100644
index 3f63c7d..0000000
--- a/res/drawable/cling_arrow_end.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/cling_arrow_right"
-        android:autoMirrored="true">
-</bitmap>
diff --git a/res/drawable/cling_arrow_start.xml b/res/drawable/cling_arrow_start.xml
deleted file mode 100644
index ebe9183..0000000
--- a/res/drawable/cling_arrow_start.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/cling_arrow_left"
-        android:autoMirrored="true">
-</bitmap>
diff --git a/res/drawable/cling_button_bg.xml b/res/drawable/cling_button_bg.xml
deleted file mode 100644
index 7bf6ce7..0000000
--- a/res/drawable/cling_button_bg.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/cling_button_pressed" />
-    <item android:drawable="@drawable/cling_button" />
-</selector>
diff --git a/res/drawable/focusable_view_bg.xml b/res/drawable/focusable_view_bg.xml
index 66661e2..e156513 100644
--- a/res/drawable/focusable_view_bg.xml
+++ b/res/drawable/focusable_view_bg.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+     Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,5 +16,11 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
-</selector>
+
+    <item android:state_focused="true">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/focused_background" />
+        </shape>
+    </item>
+
+</selector>
\ No newline at end of file
diff --git a/res/interpolator/decelerate_quart.xml b/res/interpolator/decelerate_quart.xml
new file mode 100644
index 0000000..5dc5d38
--- /dev/null
+++ b/res/interpolator/decelerate_quart.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+        android:factor="2" />
diff --git a/res/interpolator/decelerate_quint.xml b/res/interpolator/decelerate_quint.xml
new file mode 100644
index 0000000..fa89a64
--- /dev/null
+++ b/res/interpolator/decelerate_quint.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+        android:factor="2.5" />
diff --git a/res/layout-land/first_run_cling.xml b/res/layout-land/first_run_cling.xml
deleted file mode 100644
index 9baee64..0000000
--- a/res/layout-land/first_run_cling.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="first_run_portrait">
-    <FrameLayout 
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <LinearLayout
-            android:id="@+id/bubble_content"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_marginLeft="100dp"
-            android:layout_marginRight="100dp"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingAltTitleText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="10dp"
-                android:text="@string/first_run_cling_title"
-                android:textColor="#FFFFFFFF"
-                android:textSize="30sp"
-                android:gravity="center" />
-            <TextView
-                style="@style/ClingAltTitleText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:text="@string/first_run_cling_description"
-                android:textColor="#80000000"
-                android:textSize="16sp"
-                android:gravity="center" />
-        </LinearLayout>
-        <TextView
-            style="@style/ClingHintText"
-            android:id="@+id/search_bar_hint"
-            android:layout_width="160dp"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top|end"
-            android:layout_marginEnd="10dp"
-            android:layout_marginTop="65dp"
-            android:visibility="gone"
-            android:drawableTop="@drawable/cling_arrow_up"
-            android:drawablePadding="5dp"
-            android:text="@string/first_run_cling_search_bar_hint" />
-        <TextView
-            style="@style/ClingHintText"
-            android:id="@+id/custom_content_hint"
-            android:layout_width="160dp"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:layout_marginStart="10dp"
-            android:layout_marginTop="100dp"
-            android:visibility="gone"
-            android:drawableStart="@drawable/cling_arrow_left"
-            android:drawablePadding="10dp"
-            android:text="@string/first_run_cling_custom_content_hint" />
-        <TextView
-            style="@style/ClingHintText"
-            android:layout_width="160dp"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom|end"
-            android:layout_marginEnd="10dp"
-            android:layout_marginBottom="85dp"
-            android:drawableEnd="@drawable/cling_arrow_right"
-            android:drawablePadding="5dp"
-            android:text="@string/first_run_cling_create_screens_hint" />
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="20dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissFirstRunCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-land/folder_cling.xml b/res/layout-land/folder_cling.xml
deleted file mode 100644
index 86286d7..0000000
--- a/res/layout-land/folder_cling.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="folder_portrait">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="15dp"
-        android:layout_marginEnd="15dp"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:id="@+id/folder_cling_title"
-                    android:text="@string/folder_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:id="@+id/folder_cling_create_folder"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/folder_cling_create_folder" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="20dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissFolderCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index abb19f4..8cd8673 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -30,6 +30,11 @@
         android:layout_height="match_parent"
         android:fitsSystemWindows="true">
 
+        <com.android.launcher3.FocusIndicatorView
+            android:id="@+id/focus_indicator"
+            android:layout_width="52dp"
+            android:layout_height="52dp" />
+
         <!-- The workspace contains 5 screens of cells -->
         <com.android.launcher3.Workspace
             android:id="@+id/workspace"
@@ -45,38 +50,13 @@
             android:layout_gravity="end" />
 
         <include
-            android:id="@+id/qsb_bar"
-            layout="@layout/qsb_bar" />
+            android:id="@+id/search_drop_target_bar"
+            layout="@layout/search_drop_target_bar" />
 
         <include layout="@layout/overview_panel"
             android:id="@+id/overview_panel"
             android:visibility="gone" />
 
-        <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
-             that it is still visible during the transition to AllApps and doesn't overlay on
-             top of that view. -->
-        <com.android.launcher3.ScrimView
-            android:id="@+id/cling_scrim"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/first_run_cling"
-            android:id="@+id/first_run_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/workspace_cling"
-            android:id="@+id/workspace_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-
-        <include layout="@layout/folder_cling"
-            android:id="@+id/folder_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-
         <include layout="@layout/apps_customize_pane"
             android:id="@+id/apps_customize_pane"
             android:layout_width="match_parent"
diff --git a/res/layout-land/longpress_cling.xml b/res/layout-land/longpress_cling.xml
new file mode 100644
index 0000000..93bbc07
--- /dev/null
+++ b/res/layout-land/longpress_cling.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+    android:id="@+id/longpress_cling"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/cling_scrim_background"
+    android:orientation="vertical" >
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <FrameLayout
+        android:id="@+id/cling_content"
+        android:layout_width="360dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:background="@drawable/cling_bg" />
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="2" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/migration_cling.xml b/res/layout-land/migration_cling.xml
index 343f43f..307cba8 100644
--- a/res/layout-land/migration_cling.xml
+++ b/res/layout-land/migration_cling.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+     Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,88 +14,90 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/migration_cling"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    launcher:drawIdentifier="migration_landscape">
+    android:background="#FF009688"
+    android:baselineAligned="false"
+    android:gravity="center_vertical" >
+
     <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
+        android:layout_width="0dp"
         android:layout_height="match_parent"
-        android:orientation="vertical">
+        android:layout_weight="1" >
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:orientation="vertical">
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="top"
-                android:gravity="center"
-                android:text="@string/first_run_cling_title"
-                android:textSize="42dp"
-                android:textColor="#FFffffff" />
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:layout_marginBottom="0dp"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/on_boarding_welcome" />
+        <ImageView
+            android:layout_width="@dimen/cling_migration_bg_size"
+            android:layout_height="@dimen/cling_migration_bg_size"
+            android:layout_gravity="center"
+            android:background="@drawable/bg_migration_cling" />
 
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_up" />
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="25dp"
-                android:layout_marginRight="25dp"
-                android:paddingLeft="25dp"
-                android:paddingRight="25dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/migration_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/migration_cling_description" />
-            </LinearLayout>
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginLeft="25dp"
-            android:layout_marginRight="25dp"
-            android:layout_marginBottom="25dp"
-            android:orientation="vertical">
-            <Button
-                style="@style/ClingButton"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/migration_cling_copy_apps"
-                android:onClick="dismissMigrationClingCopyApps" />
-            <Button
-                style="@style/ClingButton"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/migration_cling_use_default"
-                android:onClick="dismissMigrationClingUseDefault" />
-        </LinearLayout>
+        <ImageView
+            android:layout_width="@dimen/cling_migration_logo_width"
+            android:layout_height="@dimen/cling_migration_logo_height"
+            android:layout_gravity="center"
+            android:src="@drawable/ic_migration" />
     </FrameLayout>
-</com.android.launcher3.Cling>
+
+    <LinearLayout
+        android:layout_width="@dimen/cling_migration_content_width"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/cling_migration_content_margin"
+        android:orientation="vertical"
+        android:paddingLeft="24dp"
+        android:paddingRight="24dp" >
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="8dp"
+            android:text="@string/first_run_cling_title"
+            android:textColor="#E1000000"
+            android:textSize="34sp" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-medium"
+            android:text="@string/migration_cling_title"
+            android:textColor="#E1000000"
+            android:textSize="20sp" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="24dp"
+            android:text="@string/migration_cling_description"
+            android:textColor="#99000000"
+            android:textSize="16sp" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <Button
+                android:id="@+id/cling_dismiss_migration_copy_apps"
+                style="?android:attr/buttonBarButtonStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:fontFamily="sans-serif-medium"
+                android:text="@string/migration_cling_copy_apps"
+                android:textColor="#FFFFFFFF"
+                android:textSize="14sp" />
+
+            <Button
+                android:id="@+id/cling_dismiss_migration_use_default"
+                style="?android:attr/buttonBarButtonStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:fontFamily="sans-serif-medium"
+                android:text="@string/migration_cling_use_default"
+                android:textColor="#deFFFFFF"
+                android:textSize="14sp" />
+        </LinearLayout>
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/migration_workspace_cling.xml b/res/layout-land/migration_workspace_cling.xml
deleted file mode 100644
index bf7075b..0000000
--- a/res/layout-land/migration_workspace_cling.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="migration_workspace_landscape">
-    <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <LinearLayout
-            android:id="@+id/migration_workspace_cling_bubble"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginStart="25dp"
-            android:layout_marginEnd="25dp"
-            android:orientation="vertical">
-            <LinearLayout
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_move_item" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-
-        <Button
-            style="@style/ClingButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="15dp"
-            android:layout_marginRight="20dp"
-            android:layout_gravity="bottom|right"
-            android:onClick="dismissMigrationWorkspaceCling" />
-    </FrameLayout>
-</com.android.launcher3.Cling>
diff --git a/res/layout-land/search_bar.xml b/res/layout-land/qsb.xml
similarity index 100%
rename from res/layout-land/search_bar.xml
rename to res/layout-land/qsb.xml
diff --git a/res/layout-land/workspace_cling.xml b/res/layout-land/workspace_cling.xml
deleted file mode 100644
index db33db0..0000000
--- a/res/layout-land/workspace_cling.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="workspace_portrait">
-    <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="25dp"
-        android:layout_marginEnd="25dp"
-        android:layout_marginTop="310dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:orientation="vertical">
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_up" />
-            <LinearLayout
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_move_item" />
-            </LinearLayout>
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="20dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissWorkspaceCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-port/first_run_cling.xml b/res/layout-port/first_run_cling.xml
deleted file mode 100644
index ac3939c..0000000
--- a/res/layout-port/first_run_cling.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="first_run_portrait">
-    <FrameLayout 
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <LinearLayout
-            android:id="@+id/bubble_content"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_marginLeft="100dp"
-            android:layout_marginRight="100dp"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingAltTitleText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="10dp"
-                android:text="@string/first_run_cling_title"
-                android:textColor="#FFFFFFFF"
-                android:gravity="center" />
-            <TextView
-                style="@style/ClingAltText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:text="@string/first_run_cling_description"
-                android:textColor="#80000000"
-                android:gravity="center" />
-        </LinearLayout>
-        <TextView
-            style="@style/ClingHintText"
-            android:id="@+id/search_bar_hint"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top|end"
-            android:layout_marginEnd="10dp"
-            android:layout_marginTop="65dp"
-            android:gravity="center_horizontal"
-            android:maxWidth="160dp"
-            android:visibility="gone"
-            android:drawableTop="@drawable/cling_arrow_up"
-            android:drawablePadding="5dp"
-            android:text="@string/first_run_cling_search_bar_hint" />
-        <TextView
-            style="@style/ClingHintText"
-            android:id="@+id/custom_content_hint"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top|start"
-            android:layout_marginStart="10dp"
-            android:layout_marginEnd="10dp"
-            android:layout_marginTop="100dp"
-            android:maxWidth="160dp"
-            android:visibility="gone"
-            android:drawableStart="@drawable/cling_arrow_start"
-            android:drawablePadding="10dp"
-            android:text="@string/first_run_cling_custom_content_hint" />
-        <TextView
-            style="@style/ClingHintText"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom|end"
-            android:layout_marginEnd="10dp"
-            android:layout_marginBottom="85dp"
-            android:maxWidth="180dp"
-            android:drawableEnd="@drawable/cling_arrow_end"
-            android:drawablePadding="5dp"
-            android:text="@string/first_run_cling_create_screens_hint" />
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="20dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissFirstRunCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-port/folder_cling.xml b/res/layout-port/folder_cling.xml
deleted file mode 100644
index 86286d7..0000000
--- a/res/layout-port/folder_cling.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="folder_portrait">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="15dp"
-        android:layout_marginEnd="15dp"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:id="@+id/folder_cling_title"
-                    android:text="@string/folder_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:id="@+id/folder_cling_create_folder"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/folder_cling_create_folder" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:layout_marginBottom="15dp"
-        android:layout_marginEnd="20dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissFolderCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 7400534..9e98d42 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -29,6 +29,11 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
+        <com.android.launcher3.FocusIndicatorView
+            android:id="@+id/focus_indicator"
+            android:layout_width="52dp"
+            android:layout_height="52dp" />
+
         <!-- The workspace contains 5 screens of cells -->
         <com.android.launcher3.Workspace
             android:id="@+id/workspace"
@@ -57,42 +62,8 @@
             android:layout_gravity="center_horizontal" />
 
         <include
-            android:id="@+id/qsb_bar"
-            layout="@layout/qsb_bar" />
-
-        <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
-             that it is still visible during the transition to AllApps and doesn't overlay on
-             top of that view. -->
-        <com.android.launcher3.ScrimView
-            android:id="@+id/cling_scrim"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/first_run_cling"
-            android:id="@+id/first_run_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/migration_cling"
-            android:id="@+id/migration_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/migration_workspace_cling"
-            android:id="@+id/migration_workspace_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/workspace_cling"
-            android:id="@+id/workspace_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/folder_cling"
-            android:id="@+id/folder_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
+            android:id="@+id/search_drop_target_bar"
+            layout="@layout/search_drop_target_bar" />
 
         <!-- This is the search bar voice button proxy view.  It allows us to have a larger
              touch target than the microphone constrained by the search bar bounds. -->
diff --git a/res/layout-port/longpress_cling.xml b/res/layout-port/longpress_cling.xml
new file mode 100644
index 0000000..8e35f5c
--- /dev/null
+++ b/res/layout-port/longpress_cling.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+    android:id="@+id/longpress_cling"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/cling_scrim_background" >
+
+    <FrameLayout
+        android:id="@+id/cling_content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:background="@drawable/cling_bg"
+        android:tag="crop_bg_top_and_sides" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout-port/migration_cling.xml b/res/layout-port/migration_cling.xml
index 1bffe6c..dde8dbc 100644
--- a/res/layout-port/migration_cling.xml
+++ b/res/layout-port/migration_cling.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+     Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,88 +14,93 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/migration_cling"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    launcher:drawIdentifier="migration_portrait">
-    <FrameLayout
-        android:id="@+id/content"
+    android:background="#FF009688" >
+
+    <RelativeLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical" >
+
+        <ImageView
+            android:layout_width="@dimen/cling_migration_bg_size"
+            android:layout_height="@dimen/cling_migration_bg_size"
+            android:layout_below="@+id/ic_cling_migration"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="@dimen/cling_migration_bg_shift"
+            android:src="@drawable/bg_migration_cling" />
+
+        <ImageView
+            android:id="@+id/ic_cling_migration"
+            android:layout_width="@dimen/cling_migration_logo_width"
+            android:layout_height="@dimen/cling_migration_logo_height"
+            android:layout_alignParentTop="true"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/ic_migration" />
 
         <LinearLayout
-            android:layout_width="match_parent"
+            android:layout_width="@dimen/cling_migration_content_width"
             android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:orientation="vertical">
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="top"
-                android:gravity="center"
-                android:text="@string/first_run_cling_title"
-                android:textSize="42dp"
-                android:textColor="#FFffffff" />
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:layout_marginBottom="0dp"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/on_boarding_welcome" />
+            android:layout_below="@+id/ic_cling_migration"
+            android:layout_marginStart="@dimen/cling_migration_content_margin"
+            android:orientation="vertical"
+            android:paddingLeft="24dp"
+            android:paddingRight="24dp" >
 
-            <ImageView
+            <TextView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_up" />
+                android:paddingBottom="8dp"
+                android:text="@string/first_run_cling_title"
+                android:textColor="#E1000000"
+                android:textSize="34sp" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:fontFamily="sans-serif-medium"
+                android:text="@string/migration_cling_title"
+                android:textColor="#E1000000"
+                android:textSize="20sp" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingBottom="24dp"
+                android:text="@string/migration_cling_description"
+                android:textColor="#99000000"
+                android:textSize="16sp" />
+
             <LinearLayout
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="25dp"
-                android:layout_marginRight="25dp"
-                android:paddingLeft="25dp"
-                android:paddingRight="25dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
+                android:layout_height="wrap_content" >
+
+                <Button
+                    android:id="@+id/cling_dismiss_migration_copy_apps"
+                    style="?android:attr/buttonBarButtonStyle"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:text="@string/migration_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
+                    android:layout_weight="1"
+                    android:fontFamily="sans-serif-medium"
+                    android:text="@string/migration_cling_copy_apps"
+                    android:textColor="#FFFFFFFF"
+                    android:textSize="14sp" />
+
+                <Button
+                    android:id="@+id/cling_dismiss_migration_use_default"
+                    style="?android:attr/buttonBarButtonStyle"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:text="@string/migration_cling_description" />
+                    android:layout_weight="1"
+                    android:fontFamily="sans-serif-medium"
+                    android:text="@string/migration_cling_use_default"
+                    android:textColor="#deFFFFFF"
+                    android:textSize="14sp" />
             </LinearLayout>
         </LinearLayout>
+    </RelativeLayout>
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginLeft="25dp"
-            android:layout_marginRight="25dp"
-            android:layout_marginBottom="25dp"
-            android:orientation="vertical">
-            <Button
-                style="@style/ClingButton"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/migration_cling_copy_apps"
-                android:onClick="dismissMigrationClingCopyApps" />
-            <Button
-                style="@style/ClingButton"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/migration_cling_use_default"
-                android:onClick="dismissMigrationClingUseDefault" />
-        </LinearLayout>
-    </FrameLayout>
-</com.android.launcher3.Cling>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout-port/migration_workspace_cling.xml b/res/layout-port/migration_workspace_cling.xml
deleted file mode 100644
index bc5e22f..0000000
--- a/res/layout-port/migration_workspace_cling.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="migration_workspace_portrait">
-    <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <LinearLayout
-            android:id="@+id/migration_workspace_cling_bubble"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginStart="25dp"
-            android:layout_marginEnd="25dp"
-            android:orientation="vertical">
-            <LinearLayout
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_move_item" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-
-        <Button
-            style="@style/ClingButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="15dp"
-            android:layout_marginRight="20dp"
-            android:layout_gravity="bottom|right"
-            android:onClick="dismissMigrationWorkspaceCling" />
-    </FrameLayout>
-</com.android.launcher3.Cling>
diff --git a/res/layout-port/search_bar.xml b/res/layout-port/qsb.xml
similarity index 98%
rename from res/layout-port/search_bar.xml
rename to res/layout-port/qsb.xml
index e993f78..4c9963d 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-port/qsb.xml
@@ -16,7 +16,6 @@
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    style="@style/SearchDropTargetBar"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/search_frame">
diff --git a/res/layout-port/workspace_cling.xml b/res/layout-port/workspace_cling.xml
deleted file mode 100644
index b926ca9..0000000
--- a/res/layout-port/workspace_cling.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="workspace_portrait">
-    <FrameLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:layout_marginStart="25dp"
-            android:layout_marginEnd="25dp"
-            android:layout_marginTop="30dp"
-            android:orientation="vertical">
-            <LinearLayout
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_title" />
-                <TextView
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/workspace_cling_move_item" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-
-        <LinearLayout
-            android:id="@+id/focused_hotseat_app_bubble"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom|left"
-            android:layout_marginLeft="25dp"
-            android:layout_marginBottom="90dp"
-            android:orientation="vertical"
-            android:visibility="gone">
-            <LinearLayout
-                android:paddingLeft="20dp"
-                android:paddingRight="20dp"
-                android:paddingTop="20dp"
-                android:paddingBottom="20dp"
-                android:layout_width="240dp"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:background="@drawable/cling">
-                <TextView
-                    android:id="@+id/focused_hotseat_app_title"
-                    style="@style/ClingTitleText"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content" />
-                <TextView
-                    android:id="@+id/focused_hotseat_app_description"
-                    style="@style/ClingText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content" />
-            </LinearLayout>
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="left"
-                android:layout_marginLeft="78dp"
-                android:src="@drawable/cling_arrow_down" />
-        </LinearLayout>
-    </FrameLayout>
-
-    <Button
-        style="@style/ClingButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="15dp"
-        android:layout_marginRight="20dp"
-        android:layout_gravity="bottom|right"
-        android:onClick="dismissWorkspaceCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp-port/folder_cling.xml b/res/layout-sw600dp-port/folder_cling.xml
deleted file mode 100644
index 87086cb..0000000
--- a/res/layout-sw600dp-port/folder_cling.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="folder_portrait">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="20dp"
-        android:layout_marginEnd="10dp"
-        android:layout_marginTop="@dimen/folderClingMarginTop">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/folder_cling_title"
-                android:text="@string/folder_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/folder_cling_create_folder"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/folder_cling_create_folder" />
-        </LinearLayout>
-    </FrameLayout>
-    <Button
-        style="@style/ClingButton"
-        android:id="@+id/cling_dismiss"
-        android:minWidth="168dp"
-        android:textSize="24sp"
-        android:layout_marginBottom="27dp"
-        android:layout_marginEnd="36dp"
-        android:layout_gravity="bottom|end"
-        android:onClick="dismissFolderCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp-port/longpress_cling.xml b/res/layout-sw600dp-port/longpress_cling.xml
new file mode 100644
index 0000000..b42d697
--- /dev/null
+++ b/res/layout-sw600dp-port/longpress_cling.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+    android:id="@+id/longpress_cling"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/cling_scrim_background"
+    android:orientation="vertical" >
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <FrameLayout
+        android:id="@+id/cling_content"
+        android:layout_width="360dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:background="@drawable/cling_bg" />
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="3" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw720dp-port/folder_cling.xml b/res/layout-sw720dp-port/folder_cling.xml
deleted file mode 100644
index 40d4e20..0000000
--- a/res/layout-sw720dp-port/folder_cling.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    launcher:drawIdentifier="folder_large">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginStart="@dimen/cling_text_block_offset_x"
-        android:layout_marginTop="@dimen/cling_text_block_offset_y">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:id="@+id/folder_cling_title"
-                android:text="@string/folder_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:id="@+id/folder_cling_create_folder"
-                android:layout_width="480dp"
-                android:layout_height="wrap_content"
-                android:text="@string/folder_cling_create_folder" />
-            <Button
-                style="@style/ClingButton"
-                android:id="@+id/cling_dismiss"
-                android:layout_marginTop="15dp"
-                android:onClick="dismissFolderCling" />
-        </LinearLayout>
-    </FrameLayout>
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 7dac271..6261541 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -30,6 +30,11 @@
         android:layout_height="match_parent"
         android:fitsSystemWindows="true">
 
+        <com.android.launcher3.FocusIndicatorView
+            android:id="@+id/focus_indicator"
+            android:layout_width="52dp"
+            android:layout_height="52dp" />
+
         <!-- The workspace contains 5 screens of cells -->
         <com.android.launcher3.Workspace
             android:id="@+id/workspace"
@@ -45,8 +50,8 @@
             android:layout_height="match_parent" />
 
         <include
-            android:id="@+id/qsb_bar"
-            layout="@layout/qsb_bar" />
+            android:id="@+id/search_drop_target_bar"
+            layout="@layout/search_drop_target_bar" />
 
         <include layout="@layout/overview_panel"
             android:id="@+id/overview_panel"
@@ -61,26 +66,6 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal" />
 
-        <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
-             that it is still visible during the transition to AllApps and doesn't overlay on
-             top of that view. -->
-        <include layout="@layout/first_run_cling"
-            android:id="@+id/first_run_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-        <include layout="@layout/workspace_cling"
-            android:id="@+id/workspace_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-
-        <include layout="@layout/folder_cling"
-            android:id="@+id/folder_cling"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone" />
-
         <com.android.launcher3.DrawableStateProxyView
             android:id="@+id/voice_button_proxy"
             android:layout_width="0dp"
diff --git a/res/layout-port/search_bar.xml b/res/layout-sw720dp/qsb.xml
similarity index 98%
copy from res/layout-port/search_bar.xml
copy to res/layout-sw720dp/qsb.xml
index e993f78..4c9963d 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-sw720dp/qsb.xml
@@ -16,7 +16,6 @@
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    style="@style/SearchDropTargetBar"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/search_frame">
diff --git a/res/layout-sw720dp/search_bar.xml b/res/layout-sw720dp/search_bar.xml
deleted file mode 100644
index 3276f3f..0000000
--- a/res/layout-sw720dp/search_bar.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    style="@style/SearchDropTargetBar"
-    android:background="@drawable/search_frame">
-   <!-- Global search icon -->
-   <com.android.launcher3.HolographicLinearLayout
-        style="@style/SearchButton.WithPaddingStart"
-        launcher:sourceImageViewId="@+id/search_button"
-        android:id="@+id/search_button_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
-        android:layout_centerVertical="true"
-        android:layout_alignParentStart="true"
-        android:layout_toStartOf="@+id/voice_button_container"
-        android:onClick="onClickSearchButton"
-        android:focusable="true"
-        android:clickable="true"
-        android:contentDescription="@string/accessibility_search_button">
-       <ImageView
-            android:id="@+id/search_button"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_gravity="start"
-            android:scaleType="fitCenter"
-            android:src="@drawable/ic_home_search_normal_holo"
-            android:adjustViewBounds="true" />
-    </com.android.launcher3.HolographicLinearLayout>
-
-    <!-- Voice search icon -->
-    <com.android.launcher3.HolographicLinearLayout
-        style="@style/SearchButton"
-        launcher:sourceImageViewId="@+id/voice_button"
-        android:id="@+id/voice_button_container"
-        android:layout_width="@dimen/app_icon_size"
-        android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
-        android:layout_centerVertical="true"
-        android:layout_alignParentEnd="true"
-        android:paddingEnd="8dp"
-        android:paddingRight="8dp"
-        android:onClick="onClickVoiceButton"
-        android:focusable="true"
-        android:clickable="true"
-        android:contentDescription="@string/accessibility_voice_search_button">
-        <ImageView
-            android:id="@+id/voice_button"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="end"
-            android:scaleType="fitCenter"
-            android:src="@drawable/ic_home_voice_search_holo"
-            android:adjustViewBounds="true" />
-    </com.android.launcher3.HolographicLinearLayout>
-</RelativeLayout>
diff --git a/res/layout/all_apps_button.xml b/res/layout/all_apps_button.xml
index 1b9ea08..9d6d82b 100644
--- a/res/layout/all_apps_button.xml
+++ b/res/layout/all_apps_button.xml
@@ -16,5 +16,4 @@
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/WorkspaceIcon"
-   android:focusable="true"
-   android:background="@drawable/focusable_view_bg" />
+   android:focusable="true" />
diff --git a/res/layout/application.xml b/res/layout/application.xml
index e4909dd..c21dea0 100644
--- a/res/layout/application.xml
+++ b/res/layout/application.xml
@@ -16,5 +16,4 @@
 
 <com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/WorkspaceIcon"
-   android:focusable="true"
-   android:background="@drawable/focusable_view_bg" />
+   android:focusable="true" />
diff --git a/res/layout/apps_customize_application.xml b/res/layout/apps_customize_application.xml
index 3b0fa6f..c56cdf3 100644
--- a/res/layout/apps_customize_application.xml
+++ b/res/layout/apps_customize_application.xml
@@ -14,15 +14,8 @@
      limitations under the License.
 -->
 
-<com.android.launcher3.PagedViewIcon
+<com.android.launcher3.BubbleTextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-
     style="@style/WorkspaceIcon.AppsCustomize"
-
     android:id="@+id/application_icon"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    
-    android:focusable="true"
-    android:background="@drawable/focusable_view_bg" />
+    android:focusable="true" />
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index eae216e..bf5f71b 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -16,64 +16,47 @@
 <com.android.launcher3.AppsCustomizeTabHost
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:background="#80FFFFFF">
+    android:clipChildren="false">
+
     <LinearLayout
-        android:id="@+id/apps_customize_content"
-        android:orientation="vertical"
+        android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:visibility="gone">
-        <!-- The layout_width of the tab bar gets overriden to align the content
-             with the text in the tabs in AppsCustomizeTabHost. -->
+        android:clipChildren="false"
+        android:orientation="vertical">
+
         <FrameLayout
-            android:id="@+id/tabs_container"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/apps_customize_tab_bar_height"
-            android:layout_marginTop="@dimen/apps_customize_tab_bar_margin_top"
-            android:layout_gravity="center_horizontal"
-            android:visibility="gone">
-            <com.android.launcher3.FocusOnlyTabWidget
-                android:id="@android:id/tabs"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:clipChildren="false">
+            <FrameLayout
+                android:id="@+id/fake_page_container"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_gravity="center"
-                android:gravity="start"
-                android:background="@drawable/tab_unselected_holo"
-                android:tabStripEnabled="false"
-                android:divider="@null" />
-            <include
-                android:id="@+id/market_button"
-                layout="@layout/market_button"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_gravity="end" />
-        </FrameLayout>
-        <FrameLayout
-            android:id="@android:id/tabcontent"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
+                android:clipChildren="false"
+                android:clipToPadding="false">
+                <FrameLayout
+                    android:id="@+id/fake_page"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:visibility="invisible"
+                    android:clipToPadding="false" />
+            </FrameLayout>
             <com.android.launcher3.AppsCustomizePagedView
                 android:id="@+id/apps_customize_pane_content"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
                 launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
-                launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
-                launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
                 launcher:maxGap="@dimen/workspace_max_gap"
                 launcher:pageIndicator="@+id/apps_customize_page_indicator" />
-            <FrameLayout
-                android:id="@+id/animation_buffer"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:background="#FF000000"
-                android:visibility="gone" />
-            <include
-                android:id="@+id/apps_customize_page_indicator"
-                layout="@layout/page_indicator"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal|bottom" />
         </FrameLayout>
+        <include
+            android:id="@+id/apps_customize_page_indicator"
+            layout="@layout/page_indicator"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center" />
     </LinearLayout>
 </com.android.launcher3.AppsCustomizeTabHost>
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
index 7c98b4a..e299b32 100644
--- a/res/layout/apps_customize_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -25,24 +25,45 @@
     android:background="@drawable/focusable_view_bg"
     android:focusable="true">
 
-    <!-- The preview of the widget or shortcut. -->
-    <com.android.launcher3.PagedViewWidgetImageView
-        android:id="@+id/widget_preview"
-        style="@style/PagedViewWidgetImageView"
+    <LinearLayout
+        android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:paddingTop="@dimen/app_widget_preview_padding_top"
-        android:paddingEnd="@dimen/app_widget_preview_padding_right"
-        android:paddingRight="@dimen/app_widget_preview_padding_right"
-        android:scaleType="matrix"
-        android:background="@drawable/screenpanel" />
+        android:layout_weight="1">
+        <FrameLayout
+            android:id="@+id/left_border"
+            android:layout_width="1dp"
+            android:layout_height="match_parent"
+            android:background="@color/widget_text_panel"
+            android:visibility="gone" />
+
+        <!-- The preview of the widget or shortcut. -->
+        <com.android.launcher3.PagedViewWidgetImageView
+            android:id="@+id/widget_preview"
+            style="@style/PagedViewWidgetImageView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:paddingTop="@dimen/app_widget_preview_padding_top"
+            android:paddingEnd="@dimen/app_widget_preview_padding_right"
+            android:paddingRight="@dimen/app_widget_preview_padding_right"
+            android:scaleType="matrix" />
+        <FrameLayout
+            android:id="@+id/right_border"
+            android:layout_width="1dp"
+            android:layout_height="match_parent"
+            android:background="@color/widget_text_panel"
+            android:visibility="gone" />
+    </LinearLayout>
+
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/app_widget_preview_label_margin_top"
-        android:layout_marginStart="@dimen/app_widget_preview_label_margin_left"
-        android:layout_marginEnd="@dimen/app_widget_preview_label_margin_right"
+        android:paddingTop="@dimen/app_widget_preview_label_vertical_padding"
+        android:paddingBottom="@dimen/app_widget_preview_label_vertical_padding"
+        android:paddingLeft="@dimen/app_widget_preview_label_horizontal_padding"
+        android:paddingRight="@dimen/app_widget_preview_label_horizontal_padding"
+        android:background="@color/widget_text_panel"
         android:orientation="horizontal">
         <!-- The name of the widget. -->
         <TextView xmlns:android="http://schemas.android.com/apk/res/android"
@@ -56,7 +77,7 @@
             android:fadingEdge="horizontal"
 
             android:textColor="#FFFFFFFF"
-            android:textSize="13sp"
+            android:textSize="12sp"
             android:textAlignment="viewStart"
             android:fontFamily="sans-serif-condensed"
             android:shadowRadius="2.0"
@@ -73,7 +94,7 @@
             android:layout_weight="0"
             android:gravity="start"
 
-            android:textColor="#FFAAAAAA"
+            android:textColor="#FFFFFFFF"
             android:textSize="12sp"
             android:fontFamily="sans-serif-condensed"
             android:shadowRadius="2.0"
diff --git a/res/values-sw340dp-port/dimens.xml b/res/layout/appwidget_not_ready.xml
similarity index 73%
copy from res/values-sw340dp-port/dimens.xml
copy to res/layout/appwidget_not_ready.xml
index e360565..be7c33b 100644
--- a/res/values-sw340dp-port/dimens.xml
+++ b/res/layout/appwidget_not_ready.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+     Copyright (C) 2009 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +15,6 @@
      limitations under the License.
 -->
 
-<resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">70dp</dimen>
-</resources>
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/res/layout/custom_content_page_indicator_marker.xml b/res/layout/custom_content_page_indicator_marker.xml
deleted file mode 100644
index 8fe3f8f..0000000
--- a/res/layout/custom_content_page_indicator_marker.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.launcher3.PageIndicatorMarker
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="16dp"
-    android:layout_height="16dp"
-    android:layout_gravity="center_vertical">
-    <ImageView
-        android:id="@+id/inactive"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scaleType="centerInside"
-        android:src="@drawable/custom_content_page"
-        />
-    <ImageView
-        android:id="@+id/active"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scaleType="centerInside"
-        android:src="@drawable/custom_content_page"
-        android:alpha="0"
-        android:scaleX="0.5"
-        android:scaleY="0.5"
-        />
-</com.android.launcher3.PageIndicatorMarker>
diff --git a/res/layout/custom_workspace_cling.xml b/res/layout/custom_workspace_cling.xml
deleted file mode 100644
index 3744f2e..0000000
--- a/res/layout/custom_workspace_cling.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<!-- dummy layout, to be replaced in overlays -->
-<com.android.launcher3.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:drawIdentifier="workspace_custom">
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textSize="20dp"
-        android:textColor="@android:color/holo_blue_light"
-        android:text="@string/dummy_custom_cling_error_message"
-        android:gravity="start"
-        android:layout_gravity="bottom|start"
-    />
-</com.android.launcher3.Cling>
diff --git a/res/values-sw340dp-port/dimens.xml b/res/layout/folder_application.xml
similarity index 72%
copy from res/values-sw340dp-port/dimens.xml
copy to res/layout/folder_application.xml
index e360565..b48b613 100644
--- a/res/values-sw340dp-port/dimens.xml
+++ b/res/layout/folder_application.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 
-<resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">70dp</dimen>
-</resources>
+<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
+   style="@style/WorkspaceIcon.Folder"
+   android:focusable="true" />
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index 5147f99..fd45d76 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -19,8 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:focusable="true"
-    android:background="@drawable/focusable_view_bg">
+    android:focusable="true" >
     <ImageView
         android:id="@+id/preview_background"
         android:layout_gravity="center_horizontal"
diff --git a/res/layout/longpress_cling_content.xml b/res/layout/longpress_cling_content.xml
new file mode 100644
index 0000000..47a8e97
--- /dev/null
+++ b/res/layout/longpress_cling_content.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingBottom="24dp"
+    android:paddingTop="36dp" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="36dp"
+        android:paddingRight="36dp"
+        android:text="@string/workspace_cling_longpress_title"
+        android:textColor="#E1000000"
+        android:textSize="24sp" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:paddingLeft="36dp"
+        android:paddingRight="36dp"
+        android:text="@string/workspace_cling_longpress_description"
+        android:textColor="#99000000"
+        android:textSize="16sp" />
+
+    <Button
+        android:id="@+id/cling_dismiss_longpress_info"
+        style="?android:attr/buttonBarButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginRight="12dp"
+        android:layout_marginTop="27dp"
+        android:fontFamily="sans-serif-medium"
+        android:paddingLeft="24dp"
+        android:paddingRight="24dp"
+        android:text="@string/workspace_cling_longpress_dismiss"
+        android:textColor="#FFFFFFFF"
+        android:textSize="14sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/longpress_cling_welcome_content.xml b/res/layout/longpress_cling_welcome_content.xml
new file mode 100644
index 0000000..dd4f8d7
--- /dev/null
+++ b/res/layout/longpress_cling_welcome_content.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingBottom="24dp"
+    android:paddingTop="36dp" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="8dp"
+        android:paddingLeft="36dp"
+        android:paddingRight="36dp"
+        android:text="@string/first_run_cling_title"
+        android:textColor="#E1000000"
+        android:textSize="34sp" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="5.3dp"
+        android:fontFamily="sans-serif-medium"
+        android:paddingLeft="36dp"
+        android:paddingRight="36dp"
+        android:text="@string/workspace_cling_longpress_title"
+        android:textColor="#E1000000"
+        android:textSize="20sp" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="36dp"
+        android:paddingRight="36dp"
+        android:text="@string/workspace_cling_longpress_description"
+        android:textColor="#99000000"
+        android:textSize="16sp" />
+
+    <Button
+        android:id="@+id/cling_dismiss_longpress_info"
+        style="?android:attr/buttonBarButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginRight="12dp"
+        android:layout_marginTop="27dp"
+        android:fontFamily="sans-serif-medium"
+        android:paddingLeft="24dp"
+        android:paddingRight="24dp"
+        android:text="@string/workspace_cling_longpress_dismiss"
+        android:textColor="#FFFFFFFF"
+        android:textSize="14sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/qsb_bar.xml b/res/layout/search_drop_target_bar.xml
similarity index 94%
rename from res/layout/qsb_bar.xml
rename to res/layout/search_drop_target_bar.xml
index 030acf6..2d51b93 100644
--- a/res/layout/qsb_bar.xml
+++ b/res/layout/search_drop_target_bar.xml
@@ -15,14 +15,13 @@
 -->
 <com.android.launcher3.SearchDropTargetBar
     xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/QSBBar"
+    android:orientation="horizontal"
     android:focusable="false"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
     <!-- Drag specific targets container -->
     <LinearLayout
-        style="@style/SearchDropTargetBar"
         android:id="@+id/drag_target_bar"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index 5d5f33b..4e5303a 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -20,7 +20,7 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:background="@drawable/portal_container_holo">
+    android:background="@drawable/quantum_panel">
 
     <ScrollView
         android:id="@+id/scroll_view"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 82fd344..4a4bb78 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Tuis"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android-kernprogramme"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Stel muurpapier"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d gekies"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d gekies"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d gekies"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Muurpapier %1$d van %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Het <xliff:g id="LABEL">%1$s</xliff:g> gekies"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Vee uit"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Kies prent"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Muurpapiere"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Snoei muurpapier"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Program is nie geïnstalleer nie."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Afgelaaide program in veiligmodus gedeaktiveer"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Legstukke"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Legstukke"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Wys Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Legstukke"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Niks meer spasie op jou Tuisskerms nie."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Niks meer spasie op die tuisskerm nie."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Niks meer plek op die warmlaai nie."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Hierdie legstuk is te groot vir die warmlaai."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen plek meer in die Gunstelinge-laai nie"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Hierdie legstuk is te groot vir die Gunstelinge-laai"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is geskep."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is verwyder."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" bestaan reeds."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"skryf Tuis-instellings en -kortpaaie"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Laat die program toe om die instellings en kortpaaie in Tuis te verander."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Kon nie legstuk laai nie"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Stel op"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is \'n stelselprogram en kan nie gedeïnstalleer word nie."</string>
     <string name="dream_name" msgid="1530253749244328964">"Vuurpyllanseerder"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Naamlose vouer"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"BEGIN VAN NUUTS AF"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiseer jou spasie"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Raak en hou agtergrond om muurpapier, legstukke en instellings te bestuur."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Kies \'n paar programme"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Om \'n program by jou Tuisskerm te voeg, raak en hou dit."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Muurpapiere, legstukke en instellings"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Raak en hou agtergrond om te pasmaak"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"HET DIT"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Hier\'s \'n vouer"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Om een soos dié te skep, raak en hou \'n program en skuif dit dan oor \'n ander een."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Vouer is gesluit"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Vouer hernoem na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Legstukke"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Instellings"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Wag tans…"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Laai tans af…"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installeer tans…"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nie teruggestel nie"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Verwyder almal"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Verwyder"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Soek"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Hierdie program is nie geïnstalleer nie"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Die program vir hierdie ikoon is nie geïnstalleer nie. Jy kan dit verwyder of die program soek en dit self installeer."</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 2ab010c..25931db 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"መነሻ"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android ዋና መተግበሪያዎች"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"የግድግዳ ወረቀት አዘጋጅ"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d ተመርጧል"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d ተመርጧል"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d ተመርጧል"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"የግድግዳ ወረቀት %1$d ከ%2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> ተመርጧል"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"ሰርዝ"</string>
-    <string name="pick_image" msgid="1272073934062909527">"ምስል ምረጥ"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"የግድግዳ ወረቀቶች"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"የግድግዳ ወረቀት ከርክም"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"የወረደው መተግበሪያ ደህንነቱ በተጠበቀ ሁኔታ ውስጥ ተሰናክሏል"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ፍርግሞች"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ፍርግሞች"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
@@ -47,15 +36,15 @@
     <string name="rename_folder_label" msgid="3727762225964550653">"አቃፊ ስም"</string>
     <string name="rename_folder_title" msgid="3771389277707820891">"አቃፊ ዳግም ሰይም"</string>
     <string name="rename_action" msgid="5559600076028658757">"እሺ"</string>
-    <string name="cancel_action" msgid="7009134900002915310">"ተው"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"ይቅር"</string>
     <string name="menu_item_add_item" msgid="1264911265836810421">"ወደ መነሻ ማያ ገጽ ያክሉ"</string>
     <string name="group_applications" msgid="3797214114206693605">"መተግበሪያዎች"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"አቋራጮች"</string>
     <string name="group_widgets" msgid="1569030723286851002">"ፍርግሞች"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"የመነሻ ማያ ገጾችዎ ላይ ተጨማሪ ቦታ የለም።"</string>
     <string name="out_of_space" msgid="4691004494942118364">"በዚህ መነሻ ማያ ገጽ ላይ ምንም ቦታ የለም።"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"በመትከያ ቦታው ላይ ተጨማሪ ቦታ የለም።"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"ይህ ፍርግም ለመትከያ ቦታው በጣም ትልቅ ነው።"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"በተወዳጆች መሣቢያ ውስጥ ተጨማሪ ቦታ የለም"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ይህ መግብር ወደ የተወዳጆች መሣቢያ ላይ እንዳይገባ በጣም ትልቅ ነው"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» ተፈጥሯል።"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» ተወግዶ ነበር።"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» አስቀድሞ አለ።"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"የመነሻ ቅንብሮችን እና አቋራጮችን ይጽፋል"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"መተግብሪያው ቅንብሮችን እና አቋራጮችን በመነሻ ውስጥ እንዲቀይራቸው ያስችለዋል።"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"ፍርግም የመጫን ችግር"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"ማዋቀሪያ"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"ይህ የስርዓት መተግበሪያ ነው እና ማራገፍ አይቻልም።"</string>
     <string name="dream_name" msgid="1530253749244328964">"የሮኬት ማስጀመሪያ"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"ስም-አልባ አቃፊ"</string>
@@ -106,9 +96,10 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"አዶዎችን ይቅዱ"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"እንደ አዲስ ይጀምሩ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"ቦታዎን ያደራጁ"</string>
-    <string name="workspace_cling_move_item" msgid="528201129978005352">"የግድግዳ ወረቀት፣ ምግብሮችን እና ቅንብሮችን ለማቀናበር ጀርባውን ይንኩ እና ይያዙት።"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"አንዳንድ መተግበሪያዎችን ይምረጡ"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"አንድ መተግበሪያ ወደ መነሻ ማያ ገጽዎ ለማከል ይንኩት እና ይያዙት።"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"ልጣፍ ፣ ምግብሮችን እና ቅንብሮችን ለማቀናበር ጀርባውን ይንኩ እና ይያዙት።"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"የግድግዳ ወረቀቶች፣ ንዑስ ፕሮግራሞች እና ቅንብሮች"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ለማበጀት ጀርባውን ነክተው ይያዙት"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ገባኝ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"አንድ አቃፊ እነሆ"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"አንድ እንደዚህ አይነት ለመፍጠር መተግበሪያውን ነክተው ይያዙት እና ወደ ሌላ ያንቀሳቅሱት።"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"እሺ"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"አቃፊ ተዘግቷል"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"አቃፊ <xliff:g id="NAME">%1$s</xliff:g> ተብሎ ዳግም ተሰይሟል"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"አቃፊ፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ፍርግሞች"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"የግድግዳ ወረቀቶች"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"ቅንብሮች"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"በመጠበቅ ላይ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"በማውረድ ላይ"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"በመጫን ላይ"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"የማይታወቅ"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ወደነበረበት አልተመለሰም"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"ሁሉንም አስወግድ"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"አስወግድ"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ፈልግ"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ይህ መተግበሪያ አልተጫነም"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"የዚህ አዶ መተግበሪያ አልተጫነም። ማስወገድ ወይም መተግበሪያውን መፈለግና ራስዎ መጫን ይችላሉ።"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 9134306..8b6aa02 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -21,21 +21,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"الرئيسية"</string>
-    <string name="uid_name" msgid="7820867637514617527">"تطبيقات Android الأساسية"</string>
+    <string name="uid_name" msgid="7820867637514617527">"‏تطبيقات Android الأساسية"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"تعيين خلفية"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"تم تحديد %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"تم تحديد %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"تم تحديد %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"الخلفية %1$d من %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"تم تحديد <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"حذف"</string>
-    <string name="pick_image" msgid="1272073934062909527">"اختيار صورة"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"الخلفيات"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"اقتصاص الخلفية"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"لم يتم تثبيت التطبيق."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"تم تعطيل التطبيق الذي تم تنزيله في الوضع الآمن"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"الأدوات"</string>
     <string name="widget_adder" msgid="3201040140710381657">"الأدوات"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"الأدوات"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"ليس هناك مساحة أخرى في الشاشات الرئيسية."</string>
     <string name="out_of_space" msgid="4691004494942118364">"ليس هناك مساحة أخرى في هذه الشاشة الرئيسية."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"ليست هناك مساحة أخرى في منطقة الإرساء القابلة للتخصيص."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"حجم هذه الأداة كبير للغاية بحيث لا تتسع له منطقة الإرساء القابلة للتخصيص."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"لا يوجد المزيد من الحقول في علبة المفضلة"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"هذه الأداة كبيرة جدًا مما يحول دون قبولها في علبة المفضّلة"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"تم إنشاء الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"تمت إزالة الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"الاختصار \"<xliff:g id="NAME">%s</xliff:g>\" موجود من قبل."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"كتابة إعدادات واختصارات الشاشة الرئيسية"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"للسماح للتطبيق بتغيير الإعدادات والاختصارات في الشاشة الرئيسية."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"حدثت مشكلة أثناء تحميل الأداة"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"الإعداد"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"هذا تطبيق نظام وتتعذر إزالته."</string>
     <string name="dream_name" msgid="1530253749244328964">"قاذفة صواريخ"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"مجلد بدون اسم"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"بداية جديدة"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"تنظيم مساحتك"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"المس مع الاستمرار الجزء الخلفي من صورة الشاشة لإدارة الخلفية والأدوات والإعدادات."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"اختيار بعض التطبيقات"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"لإضافة تطبيق إلى الشاشة الرئيسية، المسه مع الاستمرار."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"الخلفيات والأدوات والإعدادات"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"المس مع الاستمرار الخلفية لتخصيصها"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"حسنًا"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"إليك المجلد"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"لإنشاء مجلد مثل هذا، المس أحد التطبيقات مع استمرار اللمس، ثم حركه فوق آخر."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"موافق"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"تم إغلاق المجلد"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"تمت إعادة تسمية المجلد إلى <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"الأدوات"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"الخلفيات"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"الإعدادات"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"انتظار"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"جارٍ التنزيل"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"جارٍ التثبيت"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"غير معروفة"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"استعادة مخفقة"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"إزالة الكل"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"إزالة"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"بحث"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"لم يتم تثبيت هذا التطبيق"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"لم يتم تثبيت تطبيق لهذا الرمز. يمكنك إزالته أو البحث عن التطبيق وتثبيته يدويًا."</string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index ddcf404..2015158 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -28,6 +28,10 @@
     <string name="folder_name" msgid="7371454440695724752"></string>
     <!-- no translation found for wallpaper_instructions (563973358787555519) -->
     <skip />
+    <!-- no translation found for image_load_fail (2821429163328561136) -->
+    <skip />
+    <!-- no translation found for wallpaper_load_fail (1261270681127096352) -->
+    <skip />
     <!-- no translation found for number_of_items_selected:zero (7464587177007785408) -->
     <!-- no translation found for number_of_items_selected:one (142482526010824029) -->
     <!-- no translation found for number_of_items_selected:other (1418352074806573570) -->
@@ -177,10 +181,6 @@
     <skip />
     <!-- no translation found for workspace_cling_move_item (528201129978005352) -->
     <skip />
-    <!-- no translation found for all_apps_cling_title (34929250753095858) -->
-    <skip />
-    <!-- no translation found for all_apps_cling_add_item (400866858451850784) -->
-    <skip />
     <!-- no translation found for folder_cling_title (3894908818693254164) -->
     <skip />
     <!-- no translation found for folder_cling_create_folder (6158215559475836131) -->
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 626345a..dcd1930 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Начало"</string>
     <string name="uid_name" msgid="7820867637514617527">"Основни приложения на Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Задаване на тапета"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Избрахте %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Избрахте %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Избрахте %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Тапет %1$d от %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Избрахте <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Изтриване"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Избиране на изображение"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Тапети"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Подрязване на тапета"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Приложението не е инсталирано."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Изтегленото приложение е деактивирано в безопасния режим"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Приспособления"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Приспособления"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Приспособления"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"На началните ви екрани няма повече място."</string>
     <string name="out_of_space" msgid="4691004494942118364">"На този начален екран няма повече място."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"В трамплина няма повече място."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Това приспособление е твърде голямо за трамплина."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Няма повече място в областта с любимите"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Това приспособление е твърде голямо за областта с любимите"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Прекият път към <xliff:g id="NAME">%s</xliff:g> е създаден."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Прекият път към <xliff:g id="NAME">%s</xliff:g> бе премахнат."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Прекият път към <xliff:g id="NAME">%s</xliff:g> вече съществува."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"запис на настройките и преките пътища в Начало"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Разрешава на приложението да променя настройките и преките пътища в Начало."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Проблем при зареждане на приспособлението"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Настройване"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Това е системно приложение и не може да се деинсталира."</string>
     <string name="dream_name" msgid="1530253749244328964">"Ракетна площадка"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Папка без име"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Начален екран %1$d от %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Страница с приложения %1$d от %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Страница с приспособления %1$d от %2$d"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Добре дошли"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Персонализиране и приспособяване."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Създаване на още екрани за приложения и папки"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"Икони на прилож. ви: Копиране"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Да се импортират ли иконите и папките от старите ви начални екрани?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРАНЕ НА ИКОНИТЕ"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"СТАРТИРАНЕ ОТНАЧАЛО"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Организиране на мястото ви"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Докоснете и задръжте фона, за да управлявате тапета, приспособленията и настройките."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Изберете някои приложения"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"За да добавите приложение към началния си екран, го докоснете и задръжте."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Тапети, приспособления и настройки"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Докоснете и задръжте фона за персонализиране"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"РАЗБРАХ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ето една папка"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"За да създадете подобна, докоснете и задръжте приложение, след което го преместете върху друго."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"ОK"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Папката бе затворена"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Папката е преименувана на „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Приспособления"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Настройки"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Изчаква"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Изтегля се"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Инсталира се"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Няма информация"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Не е възстановено"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Премахване на всички"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Премахване"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Търсене"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Това приложение не е инсталирано"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Приложението за тази икона не е инсталирано. Можете да я премахнете или да потърсите приложението и да го инсталирате ръчно."</string>
 </resources>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
new file mode 100644
index 0000000..f60f1c5
--- /dev/null
+++ b/res/values-bn-rBD/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"লঞ্চার৩"</string>
+    <string name="home" msgid="7658288663002113681">"হোম"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android প্রাথমিক অ্যাপ্লিকেশানগুলি"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ডাউনলোড করা অ্যাপ্লিকেশান নিরাপদ মোডে অক্ষম রয়েছে"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"উইজেটগুলি"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"উইজেটগুলি"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"মেম দেখান"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"একটি উইজেট তুলতে তা স্পর্শ করে ধরে রাখুন৷"</string>
+    <string name="market" msgid="2619650989819296998">"দোকান"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"এই হোম স্ক্রীনে আইটেম রাখা যায়নি৷"</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"তৈরি করেতে উইজেট চয়ন করুন"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"ফোল্ডারের নাম"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"ফোল্ডার পুনঃনামকরণ করুন"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ঠিক আছে"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"বাতিল করুন"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"হোম স্ক্রীনে যোগ করুন"</string>
+    <string name="group_applications" msgid="3797214114206693605">"অ্যাপ্লিকেশানগুলি"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"শর্টকাটগুলি"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"উইজেটগুলি"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"আপনার হোম স্ক্রীনগুলিতে আর কোনো জায়গা নেই৷"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"এই হোম স্ক্রীনে আর কোনো জায়গা নেই৷"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"পছন্দসই ট্রে-তে আর কোনো জায়গা নেই"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"পছন্দসই ট্রে\'র জন্য এই উইজেটটি খুবই বড়"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"শর্টকাট \"<xliff:g id="NAME">%s</xliff:g>\" তৈরি করা হয়েছে৷"</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"শর্টকাট \"<xliff:g id="NAME">%s</xliff:g>\" সরানো হয়েছে৷"</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"শর্টকাট <xliff:g id="NAME">%s</xliff:g> আগে থেকেই আছে৷"</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"শর্টকাট চয়ন করুন"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"অ্যাপ্লিকেশান চয়ন করুন"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"অ্যাপ্লিকেশানগুলি"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"হোম"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"সরান"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"আনইনস্টল করুন"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"সরান"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"আনইনস্টল করুন"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"অ্যাপ্লিকেশানের তথ্য"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"অনুসন্ধান করুন"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"ভয়েস অনুসন্ধান"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"অ্যাপ্লিকেশানগুলি"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"সরান"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"আপডেট আনইনস্টল করুন"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"অ্যাপ্লিকেশান আনইনস্টল করুন"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"অ্যাপ্লিকেশানের বিশদ বিবরণ"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"১টি অ্যাপ্লিকেশান নির্বাচন করা হয়েছে"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"১টি উইজেট নির্বাচন করা হয়েছে"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"১টি ফোল্ডার নির্বাচন করা হয়েছে"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"১টি শর্টকাট নির্বাচন করা হয়েছে"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"শর্টকাটগুলি ইনস্টল করে"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"একটি অ্যাপ্লিকেশানকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি যোগ করার অনুমতি দেয়৷"</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"শর্টকাটগুলি আনইনস্টল করে"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"অ্যাপ্লিকেশানটিকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি সরানোর অনুমতি দেয়৷"</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"হোম সেটিংস এবং শর্টকাটগুলি পড়ে"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পড়তে দেয়৷"</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"হোম সেটিংস এবং শর্টকাটগুলি লেখে"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পরিবর্তন করতে দেয়৷"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"উইজেট লোড হতে সমস্যা হয়েছে"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"এটি একটি সিস্টেম অ্যাপ্লিকেশান এবং আনইনস্টল করা যাবে না৷"</string>
+    <string name="dream_name" msgid="1530253749244328964">"রকেট লঞ্চার"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"নামবিহীন ফোল্ডার"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"%1$d নম্বর হোম স্ক্রীন"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$dটির মধ্যে %1$dটি পৃষ্ঠা"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dটির %1$d নম্বর হোম স্ক্রীন"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$dটির মধ্যে %1$dটি অ্যাপ্লিকেশান পৃষ্ঠা"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$dটির মধ্যে %1$dটি উইজেট পৃষ্ঠা"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"স্বাগতম"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"নিজের বাড়ির মতো স্বাচ্ছন্দ্য বোধ করুন৷"</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"অ্যাপ্লিকেশান এবং ফোল্ডারগুলির জন্য আরো স্ক্রীn তৈরি করুন"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"আপনার অ্যাপ্লিকেশান আইকনগুলি অনুলিপি করুন"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"আপনার পুরানো হোম স্ক্রীন থেকে আইকন এবং ফোল্ডারগুলি আমদানি করবেন?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"আইকনগুলি অনুলিপি করুন"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"নতুন করে শুরু করুন"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"আপনার স্থান সংগঠিত করুন"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"ওয়ালপেপার, উইজেট এবং সেটিংস পরিচালনা করতে পটভূমি স্পর্শ করে ধরে রাখুন৷"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"এখানে একটি ফোল্ডার আছে"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"এটির মতো একটি তৈরি করতে, একটি অ্যাপ্লিকেশান স্পর্শ করে ধরে রাখুন, এবং তারপরে এটিকে অন্য একটির উপরে সরিয়ে নিয়ে যান৷"</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ঠিক আছে"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ফোল্ডার খোলা হয়েছে, <xliff:g id="WIDTH">%1$d</xliff:g> বাই <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"ফোল্ডার বন্ধ করতে স্পর্শ করুন"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"পুনঃনামকরণ সংরক্ষণ করতে স্পর্শ করুন"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ফোল্ডার বন্ধ করা হয়েছে"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"ফোল্ডারের নাম পাল্টে <xliff:g id="NAME">%1$s</xliff:g> করা হয়েছে"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"ফোল্ডার: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"উইজেটগুলি"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"ওয়ালপেপারগুলি"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"সেটিংস"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"প্রতীক্ষা"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ডাউনলোড হচ্ছে"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ইনস্টল করা হচ্ছে"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"পুনঃস্থাপন করা যায়নি"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"সবগুলি সরান"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"অনুসন্ধান"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"এই অ্যাপ্লিকেশানটি ইন্সটল করা নাই"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"এই আইকনের অ্যাপ্লিকেশানটি ইন্সটল করা নাই। আপনি এটি সরাতে পারেন বা অ্যাপ্লিকেশানটি অনুসন্ধান করে এটি নিজে ইন্সটল করতে পারেন।"</string>
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index fe9524b..6d10235 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Inici"</string>
     <string name="uid_name" msgid="7820867637514617527">"Aplicacions principals d\'Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Estableix el fons de pantalla"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Seleccionats: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Seleccionats: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Seleccionats: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Fons de pantalla %1$d de %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"S\'ha seleccionat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Suprimeix"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Selecciona una imatge"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fons de pantalla"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Retalla el fons de pantalla"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'aplicació que has baixat està desactivada al mode segur."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra la memòria"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"No queda espai a les pantalles d\'inici."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Ja no queda espai en aquesta pantalla d\'inici."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"No queda espai al hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Aquest widget és massa gran per al hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"No hi ha més espai a la safata Preferits."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Aquest widget és massa gran per a la safata Preferits."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"S\'ha creat la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"S\'ha suprimit la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"La drecera \"<xliff:g id="NAME">%s</xliff:g>\" ja existeix."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"escriu la configuració i les dreceres de la pantalla d\'inici"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet que l\'aplicació canviï la configuració i les dreceres de la pantalla d\'inici."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"S\'ha produït un problema en carregar el widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuració"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sense nom"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"NOU COMENÇAMENT"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organitza el teu espai"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Toca i mantén premut el fons per gestionar el fons de pantalla, els widgets i la configuració."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Tria unes quantes aplicacions"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Per afegir una aplicació a la pantalla d\'inici, mantén-la premuda."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fons de pantalla, widgets i configuració"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén premut el fons per fer personalitzacions."</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"D\'ACORD"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Aquí hi ha una carpeta"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Per crear-ne una com aquesta, mantén premuda una aplicació i, a continuació, mou-la sobre una altra."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"D\'acord"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Carpeta tancada"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"S\'ha canviat el nom de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Configuració"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"En espera"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"S\'està baixant"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instal·lant"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"No restaurat"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Suprimeix-ho tot"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Aquesta aplicació no està instal·lada"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'aplicació d\'aquesta icona no està instal·lada. Pots suprimir-la o cercar l\'aplicació i instal·lar-la manualment."</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index f323e11..f729a46 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Plocha"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Nastavit jako tapetu"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Vybráno: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Vybráno: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Vybráno: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Tapeta %1$d z %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Vybrána položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Smazat"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Vybrat obrázek"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Tapety"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Oříznutí tapety"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikace není nainstalována."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Stažená aplikace je v nouzovém režimu zakázána"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgety"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobrazit Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgety"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Na plochách již není místo."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Na této ploše již není místo."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"V sekci hotseat již není místo."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Widget je pro hotseat příliš velký."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Na panelu Oblíbené položky již není místo."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tento widget je pro panel Oblíbené položky příliš velký."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> byl vytvořen."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> byl odebrán."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> již existuje."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazů plochy"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Umožňuje aplikaci změnit nastavení a odkazy na ploše."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problém s načtením widgetu"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Nastavení"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Složka bez názvu"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ZAČÍT S VÝCHOZÍM ROZVRŽENÍM"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizace prostoru"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Chcete-li spravovat tapetu, widgety a nastavení, dotkněte se pozadí a přidržte je."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Vyberte nějaké aplikace"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Chcete-li na plochu přidat aplikaci, dotkněte se jí a přidržte ji."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Tapety, widgety a nastavení"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pozadí můžete přizpůsobit klepnutím a podržením"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ROZUMÍM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Toto je složka"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Chcete-li vytvořit složku, přetáhněte aplikaci na jinou aplikaci."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Složka je uzavřena"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Složka přejmenována na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Složka: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgety"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Nastavení"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Čekání"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Stahování"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalace"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nebylo obnoveno"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstranit vše"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Hledat"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Tato aplikace není nainstalována"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikace pro tuto ikonu není nainstalována. Můžete ikonu odstranit nebo zkusit aplikaci vyhledat a nainstalovat ručně."</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index eb80512..85159b2 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Startskærm"</string>
     <string name="uid_name" msgid="7820867637514617527">"Kerneapps i Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Angiv baggrund"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d er valgt"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d er valgt"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d er valgt"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Baggrund %1$d af %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> blev valgt"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Slet"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Vælg billede"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Baggrunde"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Beskær baggrund"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installeret."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloadet app er deaktiveret i sikker tilstand"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Der er ikke mere plads på dine startskærme."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Der er ikke mere plads på denne startskærm."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Der er ikke mere plads i hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Denne widget er for stor til hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Foretrukne"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denne widget er for stor til bakken Foretrukne"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev oprettet."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev fjernet."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" findes allerede."</string>
@@ -79,15 +68,16 @@
     <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget er valgt"</string>
     <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 mappe er valgt"</string>
     <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 genvej er valgt"</string>
-    <string name="permlab_install_shortcut" msgid="5632423390354674437">"installer genveje"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"installere genveje"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Tillader, at en app tilføjer genveje uden brugerens indgriben."</string>
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"afinstaller genveje"</string>
     <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Tillader, at appen fjerner genveje uden brugerens indgriben."</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"læs indstillinger og genveje for startskærmen"</string>
     <string name="permdesc_read_settings" msgid="5833423719057558387">"Tillader, at appen læser indstillingerne og genvejene på startskærmen."</string>
-    <string name="permlab_write_settings" msgid="3574213698004620587">"skriv indstillinger og genveje for startskærmen"</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"skrive indstillinger og genveje for startskærmen"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Tillader, at appen ændrer indstillingerne og genvejene på startskærmen."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Der er problemer med indlæsning af widgetten"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Konfigurer"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp, som ikke kan afinstalleres."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Unavngiven mappe"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"START PÅ EN FRISK"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser din arbejdsplads"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Tryk på en baggrund, og hold fingeren nede for at administrere baggrunde, widgets og indstillinger."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Vælge nogle apps"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Tryk på en app, og hold fingeren nede for at føje appen til startskærmen."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Baggrunde, widgets og indstillinger"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tryk på baggrunden, og hold fingeren nede for at tilpasse den"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK, FORSTÅET"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Her kan du se en mappe"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Du kan oprette en mappe magen til denne ved at trykke på en app og holde fingeren nede, mens du flytter appen til en anden mappe."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mappen er lukket"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mappen er omdøbt til <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Baggrunde"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Indstillinger"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Afventer"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Downloader"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installerer"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Ukendt"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ikke gendannet"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Slet alle"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Søg"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Denne app er ikke installeret"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen, der hører til dette ikon, er ikke installeret. Du kan fjerne den eller prøve at søge efter appen og installere den manuelt."</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index d0cc5aa..698a254 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Startseite"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Hintergrund auswählen"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d ausgewählt"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d ausgewählt"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d ausgewählt"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Hintergrund %1$d von %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> ausgewählt"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Entfernen"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Bild auswählen"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Hintergründe"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Hintergrund zuschneiden"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"App ist nicht installiert."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Heruntergeladene App im abgesicherten Modus deaktiviert"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Speicher anzeigen"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Auf Ihren Startbildschirmen ist kein Platz mehr vorhanden."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Auf diesem Startbildschirm ist kein Platz mehr vorhanden."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Kein Platz mehr auf der App-Leiste"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Dieses Widget ist zu groß für die App-Leiste."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Ablage \"Favoriten\" ist voll."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Dieses Widget ist zu groß für die Ablage \"Favoriten\"."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" wurde erstellt."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" wurde entfernt."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" ist bereits vorhanden."</string>
@@ -84,10 +73,11 @@
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"Verknüpfungen deinstallieren"</string>
     <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ermöglicht einer App das Entfernen von Verknüpfungen ohne Eingreifen des Nutzers"</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"Einstellungen und Verknüpfungen auf dem Startbildschirm lesen"</string>
-    <string name="permdesc_read_settings" msgid="5833423719057558387">"Ermöglicht einer App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen"</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"Einstellungen und Verknüpfungen für den Startbildschirm schreiben"</string>
-    <string name="permdesc_write_settings" msgid="5440712911516509985">"Ermöglicht einer App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem beim Laden des Widgets"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Einrichten"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Unbenannter Ordner"</string>
@@ -96,7 +86,7 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Startbildschirm %1$d von %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-Seite %1$d von %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets-Seite %1$d von %2$d"</string>
-    <string name="first_run_cling_title" msgid="2459738000155917941">"Willkommen"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Hallo!"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Gerät personalisieren"</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"Standardübersicht verwenden"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Arbeitsbereich organisieren"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Hintergrund berühren und halten, um Hintergrund, Widgets und Einstellungen zu verwalten"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Apps auswählen"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Berühren und halten Sie eine App, um sie zum Startbildschirm hinzuzufügen."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Hintergründe, Widgets &amp; Einstellungen"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Berühren und halten Sie den Hintergrund, um ihn anzupassen."</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Hier ist ein Ordner"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Um einen Ordner zu erstellen, berühren und halten Sie eine App und verschieben Sie sie auf eine andere."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Ordner geschlossen"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Ordner umbenannt in <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Hintergründe"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Einstellungen"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Warten"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Download läuft"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installation"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Unbekannt"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nicht wiederhergestellt"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Alle entfernen"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Entfernen"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Suchen"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Diese App ist nicht installiert"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Die App für dieses Symbol ist nicht installiert. Sie können das Symbol entfernen oder nach der App suchen und sie manuell installieren."</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index d28c7b6..3eec27d 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Αρχική σελίδα"</string>
     <string name="uid_name" msgid="7820867637514617527">"Βασικές εφαρμογές Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Ορισμός ταπετσαρίας"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d επιλεγμένα"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d επιλεγμένα"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d επιλεγμένα"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Ταπετσαρία %1$d από %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Επιλέχθηκε το <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Διαγραφή"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Επιλογή εικόνας"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Ταπετσαρίες"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Περικοπή ταπετσαρίας"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Η λήψη εφαρμογών απενεργοποήθηκε στην Ασφαλή λειτουργία"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Γραφικά στοιχεία"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Γραφικά στοιχεία"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Γραφικά στοιχεία"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Δεν υπάρχει άλλος χώρος στις Αρχικές οθόνες σας."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Δεν υπάρχει άλλος χώρος στη γραμμή γρήγορης πρόσβασης."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Αυτό το γραφικό στοιχείο είναι πολύ μεγάλο για τη γραμμή γρήγορης πρόσβασης."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Δεν υπάρχει επιπλέον χώρος στην περιοχή Αγαπημένα"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Αυτό το γραφικό στοιχείο είναι πολύ μεγάλο για την περιοχή Αγαπημένα."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Δημιουργήθηκε η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" καταργήθηκε."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" υπάρχει ήδη."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"εγγραφή ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Επιτρέπει στην εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Παρουσιάστηκε πρόβλημα στη φόρτωση του γραφικού στοιχείου"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Ρύθμιση"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Αυτή είναι μια εφαρμογή συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Φάκελος χωρίς όνομα"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ΝΕΑ ΕΝΑΡΞΗ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Οργανώστε το χώρο σας"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Αγγίξτε παρατεταμένα το φόντο για να διαχειριστείτε την ταπετσαρία, τα γραφικά στοιχεία και τις ρυθμίσεις."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Επιλέξτε ορισμένες εφαρμογές"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Για να προσθέσετε μια εφαρμογή στην αρχική σας οθόνη, αγγίξτε την παρατεταμένα."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ταπετσαρίες, γραφικά στοιχεία και ρυθμίσεις"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Αγγίξτε παρατεταμένα το παρασκήνιο για προσαρμογή"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ΕΓΙΝΕ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ορίστε ένας φάκελος"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Για να δημιουργήσετε έναν φάκελο σαν κι αυτόν, πατήστε παρατεταμένα μια εφαρμογή και στη συνέχεια, μετακινήστε τη πάνω σε μια άλλη."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Ο φάκελος έκλεισε"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Ο φάκελος μετονομάστηκε σε <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Γραφικά στοιχεία"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Ρυθμίσεις"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Αναμονή"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Λήψη "</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Εγκατάσταση"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Άγνωστο"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Δεν ανακτήθηκε"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Κατάργηση όλων"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Κατάργηση"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Αναζήτηση"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Αυτή η εφαρμογή δεν είναι εγκατεστημένη"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Η εφαρμογή γι\' αυτό το εικονίδιο δεν είναι εγκατεστημένη. Μπορείτε να το καταργήσετε ή να αναζητήσετε την εφαρμογή και να την εγκαταστήσετε με μη αυτόματο τρόπο."</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 4ca33f4..615e5c9 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Home"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Set wallpaper"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selected"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selected"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selected"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Wallpaper %1$d of %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Delete"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pick image"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Wallpapers"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Crop wallpaper"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"No more room on your Home screens."</string>
     <string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"No more room on the hot seat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"This widget is too large for the hot seat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"This widget is too large for the Favourites tray"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"START AFRESH"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organise your space"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Touch &amp; hold background to manage wallpaper, widgets and settings."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Choose some apps"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"To add an app to your Home screen, touch &amp; hold it."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets, &amp; settings"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Touch &amp; hold background to customise"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"GOT IT"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Here\'s a folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"To create one like this, touch &amp; hold an app, then move it over another."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folder closed"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Settings"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Waiting"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Downloading"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installing"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Not restored"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Remove All"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 4ca33f4..615e5c9 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Home"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Set wallpaper"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selected"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selected"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selected"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Wallpaper %1$d of %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Delete"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pick image"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Wallpapers"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Crop wallpaper"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"No more room on your Home screens."</string>
     <string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"No more room on the hot seat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"This widget is too large for the hot seat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"This widget is too large for the Favourites tray"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"START AFRESH"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organise your space"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Touch &amp; hold background to manage wallpaper, widgets and settings."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Choose some apps"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"To add an app to your Home screen, touch &amp; hold it."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets, &amp; settings"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Touch &amp; hold background to customise"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"GOT IT"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Here\'s a folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"To create one like this, touch &amp; hold an app, then move it over another."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folder closed"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Settings"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Waiting"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Downloading"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installing"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Not restored"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Remove All"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</string>
 </resources>
diff --git a/res/values-en/dimens.xml b/res/values-en/dimens.xml
deleted file mode 100644
index 01d4693..0000000
--- a/res/values-en/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-<!-- Cling -->
-    <dimen name="cling_title_text_size">22sp</dimen>
-    <dimen name="cling_text_size">16sp</dimen>
-    <dimen name="cling_alt_title_text_size">30sp</dimen>
-    <dimen name="cling_alt_text_size">16sp</dimen>
-    <dimen name="cling_hint_text_size">18sp</dimen>
-</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 43c2f41..31afa3e 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Pantalla principal"</string>
     <string name="uid_name" msgid="7820867637514617527">"Aplicaciones básicas de Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Establecer como fondo de pantalla"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d seleccionados"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d seleccionado"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d seleccionados"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Fondo de pantalla %1$d de %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Eliminar"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Elegir imagen"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fondos de pantalla"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Recortar fondo de pantalla"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"No se instaló la aplicación."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"No hay más espacio en tus pantallas principales."</string>
     <string name="out_of_space" msgid="4691004494942118364">"No hay más espacio en esta pantalla principal."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"No hay más espacio en la barra de accesos directos."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Este widget es demasiado grande para la barra de accesos directos."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está llena."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget es demasiado grande para la bandeja de favoritos."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Se creó el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Se eliminó el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"escribir configuración y accesos directos de la pantalla principal"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que la aplicación cambie la configuración y los accesos directos de la pantalla principal."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema al cargar el widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuración"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta es una aplicación del sistema y no se puede desinstalar."</string>
     <string name="dream_name" msgid="1530253749244328964">"Lanzacohetes"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
@@ -96,19 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla principal %1$d de %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicaciones %1$d de %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets %1$d de %2$d"</string>
-    <string name="first_run_cling_title" msgid="2459738000155917941">"Te damos la bienvenida"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenido"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Siéntete como en casa."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea más pantallas para aplicaciones y carpetas."</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"Copiar íconos de aplicaciones"</string>
-    <string name="migration_cling_description" msgid="2752413805582227644">"¿Importar íconos y carpetas de pantallas princip. antiguas?"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"¿Importar íconos y carpetas de pant. principales antiguas?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONOS"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"EMPEZAR DE CERO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza tu espacio"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén presionado el fondo para administrar el fondo de pantalla, los widgets y la configuración."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Elige algunas aplicaciones"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Para agregar una aplicación a tu pantalla principal, mantenla presionada."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos, widgets y configuración"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén presionado el fondo para personalizarlo"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDIDO"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Aquí tienes una carpeta"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear una carpeta como esta, mantén presionada una aplicación y luego muévela sobre otra."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Carpeta cerrada"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"El nombre de la carpeta se cambió a <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Configuración"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Pendiente"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"No restaurado"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todo"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación no está instalada"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación para este ícono no está instalada. Puedes eliminar el ícono o buscar la aplicación e instarla manualmente."</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 6fc4a42..4e91412 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Home"</string>
     <string name="uid_name" msgid="7820867637514617527">"Aplicaciones básicas de Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Establecer fondo"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Seleccionados: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Seleccionados: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Seleccionados: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Fondo de pantalla %1$d de %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Eliminar"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Seleccionar imagen"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fondos de pantalla"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Recortar fondo de pantalla"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"La aplicación no está instalada."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"No queda espacio en las pantallas de inicio."</string>
     <string name="out_of_space" msgid="4691004494942118364">"No queda espacio en la pantalla de inicio."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"No queda espacio en la barra de accesos directos."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Este widget es demasiado grande para la barra de accesos directos."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está completa"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget es demasiado grande para la bandeja de favoritos"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Se ha creado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Se ha eliminado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"escribir información de accesos directos y de ajustes de la pantalla de inicio"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que las aplicaciones cambien los ajustes y los accesos directos de la pantalla de inicio."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema al cargar el widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuración"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación es del sistema y no se puede desinstalar."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
@@ -104,11 +94,12 @@
     <string name="migration_cling_title" msgid="9181776667882933767">"Copiar iconos de aplicaciones"</string>
     <string name="migration_cling_description" msgid="2752413805582227644">"¿Importar iconos y carpetas de pantallas de inicio antiguas?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ICONOS"</string>
-    <string name="migration_cling_use_default" msgid="2626475813981258626">"INICIAR ACTUALIZACIÓN"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"AJUSTES PREDETERMINADOS"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza tu espacio"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén pulsado el fondo para gestionar el fondo de pantalla, los widgets y los ajustes."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Selecciona algunas aplicaciones"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Para añadir una aplicación a tu pantalla de inicio, solo tienes que mantenerla pulsada."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos de pantalla, widgets y ajustes"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén pulsado el fondo para personalizarlo"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDIDO"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Esto es una carpeta"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear una carpeta como esta, mantén pulsada una aplicación y muévela sobre otra."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Carpeta cerrada"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Se ha cambiado el nombre de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Ajustes"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Esperando"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"No restaurado"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todo"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación no está instalada"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación de este icono no está instalada. Puedes eliminar el icono o buscar la aplicación e instalarla manualmente."</string>
 </resources>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 86285ce..fa352a1 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Avaekraan"</string>
     <string name="uid_name" msgid="7820867637514617527">"Androidi tuumrakendused"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Määra taustapilt"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Valitud on %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Valitud on %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Valitud on %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%1$d/%2$d taustapildist"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Valitud on <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Kustuta"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Vali kujutis"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Taustapildid"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Taustapildi kärpimine"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Rakendus pole installitud."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Allalaetud rakendus on turvarežiimis keelatud"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Vidinad"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Vidinad"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mälu kuvamine"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Vidinad"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Teie avaekraanidel ei ole enam ruumi."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Sellel avaekraanil pole enam ruumi."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Kohandataval dokialal pole rohkem ruumi."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"See vidin on kohandatava dokiala jaoks liiga suur."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Salves Lemmikud pole rohkem ruumi"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"See vidin on salve Lemmikud jaoks liiga suur"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on loodud."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on eemaldatud."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on juba olemas."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"kirjuta avaekraani seaded ja otseteed"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Võimaldab rakendusel muuta avaekraanil seadeid ja otseteid."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Probleem vidina laadimisel"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Seadistamine"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Nimetu kaust"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ALUSTA ALGUSEST"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Korraldage oma ruumi"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Taustapildi, vidinate ja seadete haldamiseks puudutage tausta ning hoidke seda all."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Valige mõned rakendused"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Rakenduse lisamiseks avaekraanile vajutage ja hoidke seda all."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Taustapildid, vidinad ja seaded"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Kohandamiseks puudutage ja hoidke tausta all"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SELGE"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Siin on kaust"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Sarnase loomiseks vajutage ja hoidke rakendust all, seejärel viige see teise peale."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Kaust on suletud"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Kausta uus nimi: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Kaust: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Vidinad"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Seaded"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Ootamine"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Allalaadimine"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installimine"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Teadmata"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ei taastatud"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Eemalda kõik"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eemalda"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Otsing"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"See rakendus ei ole installitud"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Selle ikooni rakendust pole installitud. Saate selle eemaldada või rakendust otsida ja käsitsi installida."</string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index acd0727..3b0deb8 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -41,7 +41,6 @@
     <string name="group_applications" msgid="2103752818818161976">"Rakendused"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Otseteed"</string>
     <string name="group_widgets" msgid="6704978494073105844">"Vidinad"</string>
-    <string name="group_wallpapers" msgid="1568191644272224858">"Taustapildid"</string>
     <string name="completely_out_of_space" msgid="1759078539443491182">"Teie avakuvadel ei ole enam ruumi."</string>
     <string name="out_of_space" msgid="8365249326091984698">"Sellel avalehel pole enam ruumi."</string>
     <string name="hotseat_out_of_space" msgid="6304886797358479361">"Kohandataval dokialal pole rohkem ruumi."</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
new file mode 100644
index 0000000..4a4c959
--- /dev/null
+++ b/res/values-eu-rES/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Abiarazlea3"</string>
+    <string name="home" msgid="7658288663002113681">"Hasiera"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android-en nukleoko aplikazioak"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Aplikazioa instalatu gabe dago."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Deskargatutako aplikazioa modu seguruan desgaitu da"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Widgetak"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Widgetak"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Erakutsi memoria"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Eduki ukituta widgeta aukeratzeko."</string>
+    <string name="market" msgid="2619650989819296998">"Denda"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Ezin izan da elementua hasierako pantailan jaregin."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Aukeratu sortu beharreko widgeta"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Karpetaren izena"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Aldatu karpetaren izena"</string>
+    <string name="rename_action" msgid="5559600076028658757">"Ados"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Utzi"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Gehitu hasierako pantailan"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Aplikazioak"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Lasterbideak"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Widgetak"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Hasierako pantailetan ez dago toki gehiago."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Hasierako pantaila honetan ez dago toki gehiago."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Ez dago toki gehiago Gogokoak erretiluan"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widgeta handiegia da Gogokoak erretiluan ezartzeko"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea sortu da."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea kendu da."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea lehendik dago."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Aukeratu lasterbidea"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Aukeratu aplikazioa"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Aplikazioak"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Hasiera"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Kendu"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalatu"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Kendu"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalatu"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Aplikazioaren informazioa"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Bilaketa"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Ahots bidezko bilaketa"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikazioak"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Kendu"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalatu eguneratzea"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalatu aplikazioa"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Aplikazioaren xehetasunak"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"Aplikazio bat hautatu da"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"Widget bat hautatu da"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"Karpeta bat hautatu da"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Lasterbide bat hautatu da"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"Instalatu lasterbideak"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Erabiltzaileak ezer egin gabe lasterbideak gehitzea baimentzen die aplikazioei."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"Desinstalatu lasterbideak"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Erabiltzaileak ezer egin gabe lasterbideak kentzea baimentzen die aplikazioei."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"Irakurri hasierako ezarpenak eta lasterbideak"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Hasierako pantailako ezarpenak eta lasterbideak irakurtzea baimentzen die aplikazioei."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"Idatzi hasierako ezarpenak eta lasterbideak"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Hasierako pantailako ezarpenak eta lasterbideak aldatzea baimentzen die aplikazioei."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Arazo bat izan da widgeta kargatzean"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Sistema-aplikazioa da hau eta ezin da desinstalatu."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Izenik gabeko karpeta"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"%1$d hasierako pantaila"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$d orria"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d/%2$d hasierako pantaila"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d/%2$d aplikazio-orria"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d/%2$d widget-orria"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Ongi etorri"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Senti zaitez etxean bezala."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Sortu pantaila gehiago aplikazioak eta karpetak ezartzeko"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiatu aplikazioen ikonoak"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Ikonoak eta karpetak aurreko hasierako pantailatik inportatu?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIATU IKONOAK"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"HASI HUTSETIK"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Antolatu zure txokoa"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Eduki ukituta atzeko planoa horma-paperak, widgetak eta ezarpenak kudeatzeko."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Hortxe duzu karpeta"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Horrelako bat sortzeko, eduki ukituta aplikazio bat eta eraman beste baten gainera."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"Ados"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Karpeta ireki da: <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Karpeta ixteko, uki ezazu"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Karpetaren izen berria gordetzeko, uki ezazu"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Karpeta itxi da"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Karpetari <xliff:g id="NAME">%1$s</xliff:g> izena eman zaio"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Karpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Widgetak"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Ezarpenak"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Zain"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Deskargatzen"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalatzen"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Ezezaguna"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ez da leheneratu"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Kendu guztiak"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Kendu"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Bilatu"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Aplikazio hau ez dago instalatuta"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ikono honen aplikazioa ez dago instalatuta. Ikonoa ken dezakezu, edo aplikazioa bilatu eta eskuz instalatu."</string>
+</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 8b60f24..13f40e2 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -21,24 +21,13 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"صفحه اصلی"</string>
-    <string name="uid_name" msgid="7820867637514617527">"برنامه‌های Android Core"</string>
+    <string name="uid_name" msgid="7820867637514617527">"‏برنامه‌های Android Core"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"تنظیم کاغذدیواری"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d انتخاب شد"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d انتخاب شد"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d انتخاب شد"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"کاغذ دیواری %1$d از %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> انتخاب شده"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"حذف"</string>
-    <string name="pick_image" msgid="1272073934062909527">"انتخاب تصویر"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"کاغذدیواری‌ها"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"برش کاغذ دیواری"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"برنامه نصب نشده است."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"برنامه دانلود شده در حالت ایمن غیرفعال شد"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ابزارک‌ها"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ابزارک‌ها"</string>
-    <string name="toggle_weight_watcher" msgid="5645299835184636119">"نمایش Mem"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"‏نمایش Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"برای انتخاب ابزارک لمس کنید و نگه دارید."</string>
     <string name="market" msgid="2619650989819296998">"فروشگاه"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"ابزارک‌ها"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"فضای بیشتری در صفحات نمایش اصلی شما موجود نیست."</string>
     <string name="out_of_space" msgid="4691004494942118364">"فضای بیشتری در این صفحه اصلی موجود نیست."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"فضای بیشتری در جایگاه اتصال نیست."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"این ابزارک بیش از حد برای جایگاه اتصال بزرگ است."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"فضای بیشتری در سینی موارد دلخواه وجود ندارد"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"این ابزارک برای سینی موارد دلخواه بسیار بزرگ است"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» ایجاد شد."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» حذف شد."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» در حال حاضر وجود دارد."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"نوشتن تنظیمات و میان‌برهای صفحه اصلی"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"به برنامه اجازه می‌دهد تنظیمات و میان‌برها را در صفحه اصلی تغییر دهد."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"مشکل در بارگیری ابزارک"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"تنظیم"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"این برنامه سیستمی است و حذف نصب نمی‌شود."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"پوشه بی‌نام"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"شروع تازه"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"فضای خود را سازماندهی کنید"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"برای مدیریت کاغذدیواری، ابزارک‌ها و تنظیمات، پس‌زمینه را لمس کرده و نگه‌دارید."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"چند برنامه انتخاب کنید"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"اگر می‌خواهید برنامه‌ای را به صفحه اصلی خود اضافه کنید، آن را لمس کرده، نگه‌دارید."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"کاغذدیواری‌ها، ابزارک‌ها و تنظیمات"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"برای سفارشی کردن، پس‌زمینه را لمس کنید و نگه‌دارید"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"متوجه شدم"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"اینجا یک پوشه است"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"برای ایجاد پوشه‌ای مثل این، یک برنامه را لمس کرده و نگه‌دارید، سپس آن را روی برنامه دیگر بیاندازید."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"تأیید"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"پوشه بسته شد"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"نام پوشه به <xliff:g id="NAME">%1$s</xliff:g> تغییر کرد"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ابزارک‌ها"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"کاغذدیواری‌ها"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"تنظیمات"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"در حال انتظار"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"در حال دانلود"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"در حال نصب"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"بازیابی نشد"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"حذف همه"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"حذف"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"جستجو"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"این برنامه نصب نشده است."</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"برنامه برای این نماد نصب نشده است. می‌توانید آن را حذف کنید یا سعی کنید برنامه را جستجو کنید و آن را به صورت دستی نصب کنید."</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 673c99e..3990a16 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Aloitusruutu"</string>
     <string name="uid_name" msgid="7820867637514617527">"Androidin ydinsovellukset"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Aseta taustakuva"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d valittu"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d valittu"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d valittu"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Taustakuva %1$d/%2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Valittu: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Poista"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Valitse kuva"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Taustakuvat"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Rajaa taustakuva"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Sovellusta ei ole asennettu."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ladattu sovellus poistettiin käytöstä suojatussa tilassa"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgetit"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgetit"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Näytä muisti"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgetit"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Aloitusruuduilla ei ole enää tilaa."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Tässä aloitusruudussa ei ole enää tilaa."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Hotseatissa ei ole enää tilaa."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Tämä widget on liian suuri tähän hotseat-paikkaan."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Suosikit-valikossa ei ole enää tilaa"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tämä widget on liian suuri Suosikit-valikkoon lisättäväksi"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> luotiin."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> poistettiin."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> on jo olemassa."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"kirjoita aloitusruudun asetuksia ja pikakuvakkeita"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Antaa sovelluksen muuttaa aloitusruudun asetuksia ja pikakuvakkeita."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Ongelma ladattaessa widgetiä"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Asetus"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
     <string name="dream_name" msgid="1530253749244328964">"Sinko"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Nimetön kansio"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ALOITA ALUSTA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Järjestä tilasi"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Hallitse taustakuvaa, widgetejä ja asetuksia koskettamalla taustaa pitkään."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Valitse joitakin sovelluksia"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Voit lisätä sovelluksen aloitusruutuun koskettamalla sitä pitkään."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Taustakuvat, widgetit ja asetukset"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Muokkaa taustaa koskettamalla ja painamalla pitkään"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SELVÄ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Tässä on kansio"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Luo se seuraavasti: kosketa sovellusta pitkään ja siirrä se sitten toisen päälle."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Kansio on suljettu"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Kansion nimeksi vaihdettiin <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgetit"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Taustakuvat"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Asetukset"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Odottaa"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Ladataan"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Asennetaan"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Tuntematon"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ei palautettu"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Poista kaikki"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Poista"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Haku"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Sovellusta ei ole asennettu"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Kuvakkeen sovellusta ei ole asennettu. Voit poistaa kuvakkeen tai etsiä sovelluksen ja asentaa sen manuaalisesti."</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index bd47ad7..f428350 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Accueil"</string>
     <string name="uid_name" msgid="7820867637514617527">"Applications de base Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Définir le fond d\'écran"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d sélectionné"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d sélectionné"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d sélectionné(s)"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Fond d\'écran %1$d sur %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Sélection : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Supprimer"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Sélectionner une image"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fonds d\'écran"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Rogner le fond d\'écran"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Vous n\'avez plus d\'espace libre sur vos écrans d\'accueil."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Pas d\'espace libre sur l\'écran d\'accueil."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Vous n\'avez plus de place sur la barre d\'accès rapide."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ce widget est trop volumineux pour la barre d\'accès rapide."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Il n\'y a plus d\'espace dans la zone des favoris"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ce widget est trop volumineux pour la zone des favoris"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » a été créé."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » a été supprimé."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » existe déjà."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"enregistrer les paramètres de la page d\'accueil et des raccourcis"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problème lors du chargement du widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuration"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
     <string name="dream_name" msgid="1530253749244328964">"Lance-missile"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"DISPOSITION PAR DÉFAUT"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser son espace personnel"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Maintenez votre doigt sur l\'arrière-plan pour gérer les fonds d\'écran, les widgets et les paramètres."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Sélectionner des applications"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Pour ajouter une application à votre écran d\'accueil, maintenez votre doigt dessus."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets et paramètres"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Maintenez le doigt sur le fond d\'écran pour personnaliser"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"J\'ai compris"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Voici un dossier"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pour créer un dossier comme ça, maintenez votre doigt sur une application, puis déplacez-la sur une autre."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Dossier fermé"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Paramètres"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"En attente"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Téléchargement..."</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installation…"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Non restauré"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Tout supprimer"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Cette application n\'est pas installée"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'application liée à cette icône n\'est pas installée. Vous pouvez la supprimer ou rechercher l\'application et l\'installer manuellement."</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index ab543d0..31448f1 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Accueil"</string>
     <string name="uid_name" msgid="7820867637514617527">"Applications de base Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Définir comme fond d\'écran"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d fond d\'écran sélectionné"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d fond d\'écran sélectionné"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d fonds d\'écran sélectionnés"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Fond d\'écran %1$d sur %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> est sélectionné."</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Supprimer"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Sélectionner une image"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fonds d\'écran"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Rogner le fond d\'écran"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Vous n\'avez plus d\'espace libre sur vos écrans d\'accueil."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Pas d\'espace libre sur cet écran d\'accueil."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Vous n\'avez plus de place sur la barre d\'accès rapide."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ce widget est trop volumineux pour la barre d\'accès rapide."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Plus d\'espace disponible dans la zone de favoris."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ce widget est trop volumineux pour la zone de favoris."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été créé."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été supprimé."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" existe déjà."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"modifier les paramètres et les raccourcis de l\'écran d\'accueil"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permettre à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problème lors du chargement du widget."</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuration"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"DISPOSITION PAR DÉFAUT"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organisez votre espace"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Appuyez de manière prolongée sur l\'arrière-plan pour gérer les fonds d\'écran, les widgets et les paramètres."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Sélectionner des applications"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Pour ajouter une application à votre écran d\'accueil, appuyez dessus de manière prolongée."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets et paramètres"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Appuyez de manière prolongée sur l\'arrière-plan pour le personnaliser."</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Voici un dossier"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pour en créer un, appuyez de manière prolongée sur une application, puis déplacez-la vers une autre."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Dossier fermé"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Dossier \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Paramètres"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"En attente"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Téléchargement…"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installation…"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Non restauré"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Tout supprimer"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Cette application n\'est pas installée"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'application correspondant à cette icône n\'est pas installée. Vous pouvez supprimer cette dernière, ou essayer de rechercher l\'application et de l\'installer manuellement."</string>
 </resources>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
new file mode 100644
index 0000000..c053b07
--- /dev/null
+++ b/res/values-gl-rES/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"Inicio"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Aplicacións básicas de Android"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"A aplicación non está instalada"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Desactivouse a aplicación descargada no modo seguro"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premido un widget para seleccionalo."</string>
+    <string name="market" msgid="2619650989819296998">"Tenda"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Non se puido engadir á pantalla de inicio."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Escolle o widget que queiras crear"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Nome do cartafol"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Cambiar o nome do cartafol"</string>
+    <string name="rename_action" msgid="5559600076028658757">"Aceptar"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Engadir á pantalla de inicio"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Aplicacións"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Atallos"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Non hai máis espazo nas pantallas de inicio."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Non hai máis espazo nesta pantalla de inicio."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Non hai máis espazo na bandexa de favoritos"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget é demasiado grande para a bandexa de favoritos"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"Creouse o atallo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"Eliminouse o atallo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"O atallo \"<xliff:g id="NAME">%s</xliff:g>\" xa existe."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Escoller un atallo"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Escoller unha aplicación"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Aplicacións"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Eliminar"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Información da aplicación"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Buscar"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Busca de voz"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicacións"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar actualización"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar aplicación"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalles da aplicación"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicación seleccionada"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget seleccionado"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 cartafol seleccionado"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 atallo seleccionado"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atallos"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a unha aplicación engadir atallos sen intervención do usuario."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar atallos"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite a unha aplicación eliminar atallos sen intervención do usuario."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"ler a configuración e os atallos da pantalla de inicio"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite a unha aplicación ler a configuración e os atallos da páxina de inicio."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"modificar a configuración e os atallos da pantalla de inicio"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite a unha aplicación cambiar a configuración e os atallos da pantalla de inicio."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Produciuse un problema ao cargar o widget"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación é do sistema e non se pode desinstalar."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Lanzacohetes"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Cartafol sen nome"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"Pantalla de inicio %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"Páxina %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Páxina de aplicacións %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Páxina de widgets %1$d de %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Dámosche a benvida"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Síntete como na túa casa."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea máis pantallas para aplicacións e cartafoles"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copiar iconas das aplicacións"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Queres importar as iconas e os cartafoles doutras pantallas de inicio?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ICONAS"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"COMEZAR DE CERO"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza o espazo"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén premido o fondo para xestionar o fondo de pantalla e máis."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Isto é un cartafol"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear un igual, mantén premida a aplicación e móvea sobre outra."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Abriuse o cartafol, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Toca para pechar o cartafol"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Toca para gardar o cambio de nome"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Pechouse o cartafol"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"O cartafol cambiou o nome a <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Cartafol: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Configuración"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"En espera"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Non restaurado"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todas"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación non está instalada"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"A aplicación para esta icona non está instalada. Podes eliminala ou buscar a aplicación e instalala manualmente."</string>
+</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 3ce9531..0ae90d4 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -21,24 +21,13 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"होम"</string>
-    <string name="uid_name" msgid="7820867637514617527">"Android के मुख्य एप्लिकेशन"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android के मुख्य ऐप्लिकेशन"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"वॉलपेपर सेट करें"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d चयनित"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d चयनित"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d चयनित"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"वॉलपेपर %2$d में से %1$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"चयनित <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"हटाएं"</string>
-    <string name="pick_image" msgid="1272073934062909527">"चित्र चुनें"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"वॉलपेपर"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"वॉलपेपर काटें"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"एप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"डाउनलोड किए गए ऐप्स सुरक्षित मोड में अक्षम है"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"विजेट"</string>
     <string name="widget_adder" msgid="3201040140710381657">"विजेट"</string>
-    <string name="toggle_weight_watcher" msgid="5645299835184636119">"स्मृति दिखाएं"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"मेमोरी दिखाएं"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट को चुनने के लिए स्‍पर्श करके रखें."</string>
     <string name="market" msgid="2619650989819296998">"खरीदारी करें"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -47,70 +36,72 @@
     <string name="rename_folder_label" msgid="3727762225964550653">"फ़ोल्‍डर का नाम"</string>
     <string name="rename_folder_title" msgid="3771389277707820891">"फ़ोल्‍डर का नाम बदलें"</string>
     <string name="rename_action" msgid="5559600076028658757">"ठीक"</string>
-    <string name="cancel_action" msgid="7009134900002915310">"रद्द करें"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"रहने दें"</string>
     <string name="menu_item_add_item" msgid="1264911265836810421">"होम स्‍क्रीन में जोड़ें"</string>
-    <string name="group_applications" msgid="3797214114206693605">"एप्लिकेशन"</string>
+    <string name="group_applications" msgid="3797214114206693605">"ऐप्लिकेशन"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
     <string name="group_widgets" msgid="1569030723286851002">"विजेट"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"आपकी होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
     <string name="out_of_space" msgid="4691004494942118364">"इस होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"हॉटसीट पर स्थान शेष नहीं है."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"हॉटसीट के लि‍ए यह वि‍जेट बहुत बड़ा है."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"पसंदीदा ट्रे में और स्थान नहीं है"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"पसंदीदा ट्रे के लिए यह विजेट बहुत ही बड़ा है"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" बनाया गया."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" निकाल दिया गया था."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" पहले से मौजूद है."</string>
     <string name="title_select_shortcut" msgid="6680642571148153868">"शॉर्टकट चुनें"</string>
     <string name="title_select_application" msgid="3280812711670683644">"एप्‍लिकेशन चुनें"</string>
-    <string name="all_apps_button_label" msgid="9110807029020582876">"एप्लिकेशन"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"ऐप्लिकेशन"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"होम"</string>
     <string name="delete_zone_label_workspace" msgid="4009607676751398685">"निकालें"</string>
     <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"अनइंस्टॉल करें"</string>
     <string name="delete_target_label" msgid="1822697352535677073">"निकालें"</string>
     <string name="delete_target_uninstall_label" msgid="5100785476250872595">"अनइंस्टॉल करें"</string>
-    <string name="info_target_label" msgid="8053346143994679532">"एप्लिकेशन की जानकारी"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"ऐप्लिकेशन की जानकारी"</string>
     <string name="accessibility_search_button" msgid="1628520399424565142">"खोजें"</string>
     <string name="accessibility_voice_search_button" msgid="4637324840434406584">"बोलकर खोजें"</string>
-    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"एप्लिकेशन"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ऐप्लिकेशन"</string>
     <string name="accessibility_delete_button" msgid="6466114477993744621">"निकालें"</string>
     <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अपडेट अनइंस्‍टॉल करें"</string>
-    <string name="cab_menu_delete_app" msgid="7435191475867183689">"एप्लिकेशन अनइंस्‍टॉल करें"</string>
-    <string name="cab_menu_app_info" msgid="8593722221450362342">"एप्लिकेशन का विवरण"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"ऐप्लिकेशन अनइंस्‍टॉल करें"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"ऐप्लिकेशन का विवरण"</string>
     <string name="cab_app_selection_text" msgid="374688303047985416">"1 एप्‍लिकेशन चयनित"</string>
     <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 विजेट चयनित"</string>
     <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 फ़ोल्‍डर चयनित"</string>
     <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 शॉर्टकट चयनित"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट इंस्‍टॉल करें"</string>
-    <string name="permdesc_install_shortcut" msgid="923466509822011139">"एप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है."</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"ऐप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है."</string>
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"शॉर्टकट अनइंस्टॉल करें"</string>
-    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"एप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट निकालने देती है."</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ऐप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट निकालने देती है."</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"होम सेटिंग और शॉर्टकट पढ़ें"</string>
-    <string name="permdesc_read_settings" msgid="5833423719057558387">"एप्लिकेशन को होम में सेटिंग और शॉर्टकट पढ़ने देती है."</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"ऐप्लिकेशन को होम में सेटिंग और शॉर्टकट पढ़ने देती है."</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"होम सेटिंग और शॉर्टकट लिखें"</string>
-    <string name="permdesc_write_settings" msgid="5440712911516509985">"एप्लिकेशन को होम में सेटिंग और शॉर्टकट बदलने देती है."</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"ऐप्लिकेशन को होम में सेटिंग और शॉर्टकट बदलने देती है."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"विजेट लोड करने में समस्‍या"</string>
-    <string name="uninstall_system_app_text" msgid="4172046090762920660">"यह एक सिस्टम एप्लिकेशन है और इसे अनइंस्टॉल नहीं किया जा सकता."</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"सेटअप"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"यह एक सिस्टम ऐप्लिकेशन है और इसे अनइंस्टॉल नहीं किया जा सकता."</string>
     <string name="dream_name" msgid="1530253749244328964">"रॉकेट लॉन्‍चर"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"अनामित फ़ोल्डर"</string>
     <string name="workspace_description_format" msgid="2950174241104043327">"होम स्‍क्रीन %1$d"</string>
     <string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d में से %1$d"</string>
     <string name="workspace_scroll_format" msgid="8458889198184077399">"होम स्क्रीन %2$d में से %1$d"</string>
-    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"एप्लिकेशन पृष्ठ %2$d में से %1$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"ऐप्लिकेशन पृष्ठ %2$d में से %1$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"विजेट पृष्ठ %2$d में से %1$d"</string>
     <string name="first_run_cling_title" msgid="2459738000155917941">"स्वागत है"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"जैसा चाहें वैसा उपयोग करें."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
-    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"एप्लिकेशन और फ़ोल्डर के लिए और अधिक स्क्रीन बनाएं"</string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ऐप्लिकेशन और फ़ोल्डर के लिए और अधिक स्क्रीन बनाएं"</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"ऐप्स आइकन की प्रतिलिपि बनाएं"</string>
     <string name="migration_cling_description" msgid="2752413805582227644">"अपनी पुरानी होम स्क्रीन से आइकन और फ़ोल्डर आयात करें?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"आइकन की प्रतिलिपि बनाएं"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"फिर से शुरू करें"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"अपने स्थान को व्यवस्थित करें"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, विजेट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"कुछ एप्लिकेशन चुनें"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"किसी एप्लिकेशन को अपनी होम स्‍क्रीन से जोड़ने के लिए, उसे स्‍पर्श करके रखें."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, विजेट और सेटिंग"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"पृष्ठभूमि कस्टमाइज़ करने के लिए स्पर्श करके रखें"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"समझ लिया"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"यहां एक फ़ोल्डर है"</string>
-    <string name="folder_cling_create_folder" msgid="6158215559475836131">"इसके जैसा कोई एक बनाने के लिए, किसी एप्लिकेशन को स्पर्श करके रखें, फिर इसे किसी दूसरे पर ले जाएं."</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"इसके जैसा कोई एक बनाने के लिए, किसी ऐप्लिकेशन को स्पर्श करके रखें, फिर इसे किसी दूसरे पर ले जाएं."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"ठीक"</string>
     <string name="folder_opened" msgid="94695026776264709">"फ़ोल्डर खोला गया, <xliff:g id="WIDTH">%1$d</xliff:g> गुणा <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"फ़ोल्‍डर बंद करने के लिए स्‍पर्श करें"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"फ़ोल्डर बंद किया गया"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"सेटिंग"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षा में"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड हो रहा है"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"इंस्टॉल हो रहा है"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"पुन:स्थापित नहीं हुआ"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"सभी निकालें"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"खोजें"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"यह ऐप्स इंस्टॉल नहीं है"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"इस आइकन का ऐप्स इंस्टॉल नहीं है. आप उसे निकाल सकते हैं या ऐप्स की खोज करके उसे मैन्युअल रूप से इंस्टॉल कर सकते हैं."</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index cc2bab8..c881077 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Početna"</string>
     <string name="uid_name" msgid="7820867637514617527">"Matične aplikacije za Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Postavi pozadinsku sliku"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Odabrano: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Odabrano: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Odabrano: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%1$d. pozadinska slika od %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Odabrana je stavka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Izbriši"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Odaberi sliku"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Pozadinske slike"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Obreži pozadinsku sliku"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Preuzeta aplikacija onemogućena je u Sigurnom načinu rada"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgeti"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Prikaži mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgeti"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Na vašim početnim zaslonima više nema mjesta."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Na ovom početnom zaslonu više nema mjesta."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Na hotseatu više nema mjesta."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ovaj je widget prevelik za hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora na traci Favoriti"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget je prevelik za traku Favoriti"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Izrađen je prečac za \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Uklonjen je prečac za \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Prečac za \"<xliff:g id="NAME">%s</xliff:g>\" već postoji."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"pisanje postavki početnog zaslona i prečaca"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Aplikaciji omogućuje promjenu postavki i prečaca na početnom zaslonu."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem pri učitavanju widgeta"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Postavljanje"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
     <string name="dream_name" msgid="1530253749244328964">"Lansirna rampa"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"POKRENI NOVO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizirajte svoj prostor"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Dodirnite i držite pozadinu da biste upravljali pozadinskom slikom, widgetima i postavkama."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Odaberite neke aplikacije"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Da biste dodali aplikaciju na početni zaslon, dodirnite je i zadržite."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadinske slike, widgeti i postavke"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Dodirnite i zadržite pozadinu radi prilagodbe"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SHVAĆAM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Evo mape"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Da biste izradili ovakvu mapu, dodirnite i držite aplikaciju pa je pomaknite preko druge aplikacije."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"U redu"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mapa je zatvorena"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mapa je preimenovana u <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgeti"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadinske slike"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Postavke"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Čekanje"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Preuzimanje"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instaliranje"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nije vraćeno"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Ukloni sve"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Traži"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacija nije instalirana"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija ove ikone nije instalirana. Možete je ukloniti ili potražiti aplikaciju i instalirati je ručno."</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 8a769f5..08d3095 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Főoldal"</string>
     <string name="uid_name" msgid="7820867637514617527">"Alap Android-alkalmazások"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Háttérkép beállítása"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d kiválasztva"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d kiválasztva"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d kiválasztva"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%2$d/%1$d. háttérkép"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> kiválasztva"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Törlés"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Kép választása"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Háttérképek"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Háttérkép körbevágása"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Az alkalmazás nincs telepítve."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"A letöltött alkalmazás Csökkentett módban ki van kapcsolva"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Modulok"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Modulok"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem. megjelenítése"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Modulok"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Nincs több hely a kezdőképernyőkön."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Nincs több hely ezen a kezdőképernyőn."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Nincs több hely az egyéni mezőben."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ez a modul túl nagy az egyéni mező számára."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Nincs több hely a Kedvencek tálcán"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ez a modul túl nagy a Kedvencek tálcán való elhelyezéshez"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon létrehozva."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon eltávolítva."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon már létezik."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"Főoldal beállításainak és parancsikonjainak írása"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a kezdőképernyő beállításait és parancsikonjait."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Probléma történt a modul betöltésekor"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Beállítás"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ez egy rendszeralkalmazás, és nem lehet eltávolítani."</string>
     <string name="dream_name" msgid="1530253749244328964">"Aknavető"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Névtelen mappa"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"TELJESEN ÚJ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Munkaterület rendezése"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Érintse meg és tartsa lenyomva a hátteret a háttérkép, modulok és beállítások kezeléséhez."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Válasszon ki néhány alkalmazást"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Ha egy alkalmazást szeretne elhelyezni a kezdőképernyőn, érintse meg, és tartsa lenyomva."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Háttérképek, modulok és beállítások"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Érintse meg és tartsa lenyomva a személyre szabáshoz"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"MEGÉRTETTEM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Itt egy mappa"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Mappa létrehozásához érintse meg és tartsa lenyomva az alkalmazást, majd húzza egy másik fölé."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mappa lezárva"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"A mappa új neve: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Modulok"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Beállítások"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Várakozik"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Letöltés alatt"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Települ"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Ismeretlen"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nincs visszaállítva"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Az összes eltávolítása"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eltávolítás"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Keresés"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Az alkalmazás nincs telepítve"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Az ikonhoz tartozó alkalmazás nincs telepítve. Törölheti az ikont, vagy az alkalmazás megkeresése után manuálisan telepítheti azt."</string>
 </resources>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index b4cdbb7..4ec39c8 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Հիմնական"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Սահմանել պաստառը"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d ընտրված"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d ընտրված"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d ընտրված"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%1$d պաստառ՝ %2$d-ից"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Ընտրված է <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Ջնջել"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Ընտրել պատկեր"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Պաստառներ"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Եզրատել պաստառը"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ներբեռնված ծրագիրն անջատված է Անվտանգ ռեժիմում"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Վիջեթներ"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Վիջեթներ"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Այլևս տեղ չկա ձեր հիմնական էկրաններին:"</string>
     <string name="out_of_space" msgid="4691004494942118364">"Այլևս տեղ չկա այս հիմնական էկրանին:"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Թեժ նստատեղերում այլևս տեղ չկա:"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Այս վիջեթը չափազանց մեծ է թեժ նստատեղերի համար:"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Ընտրյալների ցուցակում այլևս ազատ տեղ չկա"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Այս վիջեթը շատ մեծ է Ընտրյալների ցուցակի համար"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումը ստեղծված է:"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումը հեռացվեց:"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումն արդեն գոյություն ունի:"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"ստեղծել հիմնաէջի կարգավորումներ ու դյուրանցումներ"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ծրագրին թույլ է տալիս փոփոխել հիմնաէջի կարգավորումներն ու դյուրանցումները:"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Վիջեթի բեռնման խնդիր կա"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Կարգավորում"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Սա համակարգային ծրագիր է և չի կարող ապատեղադրվել:"</string>
     <string name="dream_name" msgid="1530253749244328964">"Հրթիռային թողարկիչ"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Անանուն թղթապանակ"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ՄԵԿՆԱՐԿԵԼ ԸՍՏ ԿԱՆԽԱԴՐՎԱԾԻ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Կառավարեք ձեր տարածությունը"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Հպեք և պահեք հետնաշերտի վրա՝ պաստառները, վիջեթներն ու կարգավորումները կառավարելու համար:"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Ընտրեք ինչ-որ ծրագիր"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Ձեր հիմնական էկրանին ծրագիր ավելացնելու համար հպեք և պահեք այն:"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Պաստառներ, վիջեթներ և կարգավորումներ"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Հարմարեցնելու համար հպեք և պահեք հետնաշերտի վրա"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ՀԱՍԿԱՆԱԼԻ Է"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ահա մի թղթապանակ"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Նման թղթապանակ ստեղծելու համար հպեք և պահեք որևէ ծրագրի վրա, ապա տեղաշարժեք այն մեկ ուրիշ ծրագրի վրա:"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Լավ"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Թղթապանակը փակ է"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Թղթապանակը վերանվանվեց <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Թղթապանակ՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Վիջեթներ"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Պաստառներ"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Կարգավորումներ"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Առկախ է"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Ներբեռնվում է"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Տեղադրվում է"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Չի վերականգնվել"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Հեռացնել բոլորը"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Գտնել"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Այս ծրագիրը տեղադրված չէ:"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Այս պատկերակի ծրագիրը տեղադրված չէ: Դուք կարող եք հեռացնել այն կամ գտնել ծրագիրը և տեղադրել այն ձեռքով:"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 7bd8d7d..137e3cc 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Layar Utama"</string>
     <string name="uid_name" msgid="7820867637514617527">"Aplikasi Inti Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Setel wallpaper"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d dipilih"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d dipilih"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d dipilih"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Wallpaper %1$d dari %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> terpilih"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Hapus"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pilih gambar"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Wallpaper"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Pangkas wallpaper"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplikasi yang diunduh dinonaktifkan dalam mode Aman"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Tampilkan Memori"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Tidak ada ruang lagi di layar Utama Anda."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Tidak ada ruang lagi pada layar Utama ini."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Tidak ada ruang lagi di hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Widget ini terlalu besar untuk hotseat tersebut."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget ini terlalu besar untuk baki Favorit"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah dibuat."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dihapus."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah ada."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"menulis setelan dan pintasan layar Utama"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Mengizinkan aplikasi mengubah setelan dan pintasan di layar Utama."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Masalah memuat widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Siapkan"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"MULAI DARI AWAL"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Kelola ruang Anda"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Sentuh lama latar belakang untuk mengelola wallpaper, widget, dan setelan."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Pilih beberapa aplikasi"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Untuk menambah aplikasi ke layar Utama Anda, sentuh lama aplikasi tersebut."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpaper, widget, &amp; setelan"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Sentuh &amp; tahan latar belakang untuk menyesuaikan"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"MENGERTI"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ini adalah folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Untuk membuat seperti yang ini, sentuh lama aplikasi, lalu pindahkan ke atas aplikasi lain."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Oke"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folder ditutup"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Folder diganti namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpaper"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Setelan"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Menunggu"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Mengunduh"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Memasang"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Tidak dikenal"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Tak dipulihkan"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Buang Semua"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Buang"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Telusuri"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Aplikasi ini belum terpasang"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikasi untuk ikon ini belum dipasang. Anda dapat membuangnya, atau menelusuri aplikasi dan memasangnya secara manual."</string>
 </resources>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
new file mode 100644
index 0000000..71f0ede
--- /dev/null
+++ b/res/values-is-rIS/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"Heim"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Kjarnaforrit Android"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Forritið er ekki uppsett."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Sótt forrit er óvirkt í öryggisstillingu"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Græjur"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Græjur"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Sýna minni"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Haltu fingri á græju til að grípa hana."</string>
+    <string name="market" msgid="2619650989819296998">"Verslun"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Ekki er hægt að sleppa atriði á þennan heimaskjá."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Veldu græju til að búa til"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Möppuheiti"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Endurnefna möppu"</string>
+    <string name="rename_action" msgid="5559600076028658757">"Í lagi"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Hætta við"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Bæta á heimaskjá"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Forrit"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Flýtileiðir"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Græjur"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Heimaskjáirnir þínir eru fullskipaðir."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Ekki meira pláss á þessum heimaskjá."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Ekki meira pláss í bakka fyrir uppáhald"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Þessi græja er of stór fyrir bakkann fyrir uppáhald"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ var búin til."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ var fjarlægð."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ er þegar til."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Veldu flýtileið"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Veldu forrit"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Forrit"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Heim"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Fjarlægja"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Eyða"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Fjarlægja"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Eyða"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Upplýsingar um forrit"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Leita"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Raddleit"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Forrit"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Fjarlægja"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Fjarlægja uppfærslu"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Fjarlægja forrit"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Upplýsingar um forrit"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 forrit valið"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 græja valin"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 mappa valin"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 flýtileið valin"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"setja upp flýtileiðir"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Leyfir forriti að bæta við flýtileiðum án íhlutunar notanda."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"fjarlægja flýtileiðir"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Leyfir forriti að fjarlægja flýtileiðir án íhlutunar notanda."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"lesa stillingar og flýtileiðir heimaskjás"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Leyfir forriti að lesa stillingar og flýtileiðir heimaskjás."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"skrifa stillingar og flýtileiðir heimaskjás"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Leyfir forriti að breyta stillingum og flýtileiðum heimaskjás."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Vandamál við að hlaða græju"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Þetta er kerfisforrit sem ekki er hægt að fjarlægja."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Eldflaugapallur"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Ónefnd mappa"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"Heimaskjár %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"Síða %1$d af %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Heimaskjár %1$d af %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Forritasíða %1$d af %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Græjusíða %1$d af %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Komdu fagnandi"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Komdu þér vel fyrir."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Búðu til fleiri skjái fyrir forrit og möppur"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Afritaðu forritatáknin þín"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Flytja inn tákn og möppur af eldri heimaskjáum?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"AFRITA TÁKN"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"BYRJA UPP Á NÝTT"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Settu hlutina á sína staði"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Haltu inni á bakgrunni til að stjórna veggfóðri, græjum og stillingum."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Hér er mappa"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Til að búa til svona skaltu draga forrit yfir á annað forrit."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"Í lagi"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Mappa opnuð, <xliff:g id="WIDTH">%1$d</xliff:g> sinnum <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Snertu til að loka möppunni"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Snertu til að staðfesta nýtt heiti"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Möppu lokað"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Heiti möppu breytt í <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Græjur"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Veggfóður"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Stillingar"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Bíður"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Sækir"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Setur upp"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Óþekkt"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ekki endurheimt"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Fjarlægja öll"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjarlægja"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Leita"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Þetta forrit er ekki uppsett"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Forritið fyrir þetta tákn er ekki uppsett. Þú getur fjarlægt það eða leitað að forritinu og sett það upp handvirkt."</string>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 941852c..b01b251 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Home page"</string>
     <string name="uid_name" msgid="7820867637514617527">"Applicazioni di base Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Imposta sfondo"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selezionati"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selezionato"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selezionati"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Sfondo %1$d di %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Elemento selezionato: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Elimina"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Scegli immagine"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Sfondi"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Ritaglia sfondo"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"App non installata."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'app scaricata è stata disattivata in modalità provvisoria"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Spazio nelle schermate Home esaurito."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Spazio nella schermata Home esaurito."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Spazio nell\'area hotseat esaurito."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Questo widget è troppo grande per l\'area hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Spazio esaurito nella barra dei Preferiti"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Questo widget è troppo grande per la barra dei Preferiti"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" creata."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"La scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" è stata rimossa."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" già presente."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"creazione di impostazioni e scorciatoie in Home"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Consente all\'app di modificare le impostazioni e le scorciatoie in Home."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Errore durante il caricamento del widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configurazione"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Questa è un\'app di sistema e non può essere disinstallata."</string>
     <string name="dream_name" msgid="1530253749244328964">"Lanciamissili"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Cartella senza nome"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"RICOMINCIA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizza il tuo spazio"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Tocca e tieni premuto lo sfondo per gestire sfondi, widget e impostazioni."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Scegli alcune applicazioni"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Per aggiungere un\'app alla schermata Home, tocca e tieni premuto."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Sfondi, widget e impostazioni"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tocca lo sfondo e tieni premuto per personalizzare"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ecco una cartella"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Per crearne una simile, tocca un\'app e tieni premuto, dopodiché spostala sopra un\'altra."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Cartella chiusa"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Nome della cartella sostituito con <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Impostazioni"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"In attesa"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Download..."</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installazione..."</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Non ripristinato"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Rimuovi tutto"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"L\'app non è installata"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'app per questa icona non è installata. Puoi rimuoverla o cercare l\'app e installarla manualmente."</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 2e1df54..6318207 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -21,21 +21,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"דף הבית"</string>
-    <string name="uid_name" msgid="7820867637514617527">"אפליקציות הליבה של Android"</string>
+    <string name="uid_name" msgid="7820867637514617527">"‏אפליקציות הליבה של Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"הגדר טפט"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d נבחרו"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d נבחרו"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d נבחרו"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"טפט %1$d מתוך %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"בחרת <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"מחק"</string>
-    <string name="pick_image" msgid="1272073934062909527">"בחר תמונה"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"טפטים"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"חתוך את הטפט"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"האפליקציה לא מותקנת."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"אפליקציה שהורדת הושבתה במצב בטוח"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"רכיבי ווידג\'ט"</string>
     <string name="widget_adder" msgid="3201040140710381657">"רכיבי ווידג\'ט"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"רכיבי ווידג\'ט"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"אין יותר מקום במסכי דף הבית."</string>
     <string name="out_of_space" msgid="4691004494942118364">"אין עוד מקום במסך דף הבית הזה."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"אין יותר מקום בפס האפליקציות."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"הווידג\'ט הזה גדול מדי עבור פס האפליקציות."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"אין עוד מקום במגש המועדפים"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"הווידג\'ט הזה גדול מדי עבור מגש המועדפים."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' נוצר."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' הוסר."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' כבר קיים."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"כתוב הגדרות וקיצורי דרך של דף הבית"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"מאפשר לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"בעיה בטעינת ווידג\'ט"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"הגדר"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"זוהי אפליקציית מערכת ולא ניתן להסיר את התקנתה."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"תיקיה ללא שם"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"התחל דף חדש"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"ארגן את אזור העבודה שלך"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"גע נגיעה רציפה ברקע כדי לנהל את הטפט, רכיבי הווידג\'ט וההגדרות."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"בחר כמה אפליקציות"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"כדי להוסיף אפליקציה למסך דף הבית, גע בה נגיעה רציפה."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"טפטים, ווידג\'טים והגדרות"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"גע והחזק ברקע לביצוע התאמה אישית"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"הבנתי"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"הנה תיקייה"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"כדי ליצור תיקייה כזו, גע נגיעה רציפה באפליקציה, ולאחר מכן גרור ושחרר אותו על-גבי אפליקציה אחרת."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"אישור"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"התיקיה נסגרה"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"שם התיקיה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"תיקיה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"רכיבי ווידג\'ט"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"טפטים"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"הגדרות"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"ממתין"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"מוריד"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"מתקין"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"לא שוחזרה"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"הסר את הכל"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"הסר"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"חפש"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"אפליקציה זו אינה מותקנת"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"האפליקציה של סמל זה אינה מותקנת. ניתן להסיר אותו, או לחפש את האפליקציה ולהתקין אותה ידנית."</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index bac3494..232845a 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"ホーム"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"壁紙を設定"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d件選択済み"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d件選択済み"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d件選択済み"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"壁紙: %1$d/%2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"選択: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"削除"</string>
-    <string name="pick_image" msgid="1272073934062909527">"画像を選択"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"壁紙"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"壁紙をトリミング"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"このアプリはインストールされていません。"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ダウンロードしたアプリは、セーフモードでは無効です"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ウィジェット"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ウィジェット"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"ウィジェット"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"ホーム画面に空きスペースがありません。"</string>
     <string name="out_of_space" msgid="4691004494942118364">"このホーム画面に空きスペースがありません。"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"ホットシートに空きスペースがありません。"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"このウィジェットはホットシートには大きすぎます。"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"お気に入りトレイに空きスペースがありません"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"このウィジェットはお気に入りトレイには大きすぎます"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を作成しました。"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を削除しました。"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」は既に存在します。"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"ホームの設定とショートカットの書き込み"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ホームの設定とショートカットの変更をアプリに許可します。"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"ウィジェットを表示できません"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"セットアップ"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"このシステムアプリはアンインストールできません。"</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"名前のないフォルダ"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"ホーム画面: %1$d/%2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"アプリの%1$d/%2$dページ"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ウィジェットの%1$d/%2$dページ"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"ようこそ"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"ホームをカスタマイズします。"</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"アプリとフォルダの画面をもっと作成します"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"アプリのアイコンをコピー"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"古いホーム画面からアイコンとフォルダをインポートしますか?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"アイコンをコピー"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"初期状態にリセットする"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"スペースを整理"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"壁紙、ウィジェット、設定を管理するには、背景を押し続けます。"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"アプリの選択"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"アプリをホーム画面に追加するにはアプリを押し続けます。"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"壁紙、ウィジェット、設定"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"カスタマイズするにはバックグラウンドを押し続けます"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"これがフォルダです"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"これと同じフォルダを作成するには、アプリを押し続けてから別のアプリの上に移動します。"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"フォルダは閉じています"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"フォルダの名前を「<xliff:g id="NAME">%1$s</xliff:g>」に変更しました"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ウィジェット"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"壁紙"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"待機中"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ダウンロード中"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"インストール中"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"復元失敗"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"すべて削除"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"削除"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"検索"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"このアプリはインストールされていません"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"このアイコンのアプリはインストールされていません。このアイコンは削除できます。または、手動でアプリを検索してインストールしください。"</string>
 </resources>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 0ed5982..2fb51f5 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"მთავარი"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android-ის ბირთვის აპები"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"ფონის დაყენება"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"არჩეულია %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"არჩეულია %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"არჩეულია %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"ფონი %1$d %2$d-დან"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"არჩეულია <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"წაშლა"</string>
-    <string name="pick_image" msgid="1272073934062909527">"სურათის ამორჩევა"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"ფონები"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"ფონის ჩამოჭრა"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"აპი არ არის დაყენებული."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"უსაფრთხო რეჟიმში ჩამოტვირთული აპი გაუქმებულია"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ვიჯეტები"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"ვიჯეტები"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"მთავარ ეკრანებზე ადგილი აღარ არის."</string>
     <string name="out_of_space" msgid="4691004494942118364">"ამ მთავარ ეკრანზე ადგილი აღარ არის."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"hotseat-ში მეტი ადგილი არ არის."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"ეს ვიჯეტი ძალიან დიდია hotseat-ისთვის."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"რჩეულების თაროზე ადგილი არ არის"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ეს ვიჯეტი ძალიან დიდია რჩეულების თაროსთვის"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"შეიქმნა მალსახმობი „<xliff:g id="NAME">%s</xliff:g>“."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"მასლახმობი „<xliff:g id="NAME">%s</xliff:g>“ წაშლილია."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"მალსახმობი „<xliff:g id="NAME">%s</xliff:g>“ უკვე არსებობს."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების ჩაწერა"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების შეცვლის უფლების მიცემა."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"პრობლემა ვიჯეტის ჩატვირთვისას"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"დაყენება"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"ეს სისტემური აპია და მისი წაშლა შეუძლებელია."</string>
     <string name="dream_name" msgid="1530253749244328964">"ფეიერვერკი"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"უსახელო საქაღალდე"</string>
@@ -102,13 +92,14 @@
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"აპებისა და საქაღალდეებისთვის კიდევ ერთი ეკრანის შექმნა"</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"თქვენი აპის ხატულების კოპირება"</string>
-    <string name="migration_cling_description" msgid="2752413805582227644">"გსურთ ძვლი მთავარი ეკრანიდან ხატულების და საქაღ. იმპორტი?"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"გსურთ, ძველი მთავარი ეკრანიდან ხატულების და საქაღ. იმპორტი?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"ხატულების კოპირება"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"სტანდარტული განლაგება"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"თქვენი სივრცის ორგანიზება"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"თუ გსურთ ფონების, ვიჯეტების და პარამეტრების მართვა, შეეხეთ და არ აუშვათ ფონს."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"აირჩიეთ რამდენიმე აპი"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"აპის მთავარ ეკრანზე დასამატებლად შეეხეთ მის ხატულას და არ აუშვათ."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები, &amp; პარამეტრები"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"მოსარგებად შეეხეთ &amp; დააყოვნეთ ფონზე"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"გასაგებია"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"აი, საქაღალდე"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"ასეთის შესაქმნელად, შეეხეთ და დააყოვნეთ აპზე, ხოლო შემდეგ გადააჩოჩეთ შემდეგზე."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"კარგი"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"საქაღალდე დაიხურა"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"საქაღალდეს შეეცვალა სახელი „<xliff:g id="NAME">%1$s</xliff:g>“-ად"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"საქაღალდე: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ვიჯეტები"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ფონები"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"პარამეტრები"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"მოცდა..."</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ჩამოტვირთვა..."</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ინსტალაცია..."</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"უცნობი"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"არ აღდგა"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"ყველას ამოშლა"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ამოშლა"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ძიება"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ეს აპი დაყენებული არ არის"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ამ ხატულის აპი დაყენებული არ არის. შეგიძლიათ ამოშალოთ, ან მოიძიოთ აპი და ხელით მოახდინოთ მისი ინსტალაცია."</string>
 </resources>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
new file mode 100644
index 0000000..288129a
--- /dev/null
+++ b/res/values-kk-rKZ/strings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"Негізгі"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android Core қолданбалары"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Қолданба орнатылмаған."</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Виджеттер"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Виджеттер"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Жадты көрсету"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетті таңдау үшін түртіп, мықтап ұстаңыз."</string>
+    <string name="market" msgid="2619650989819296998">"Дүкен"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Элементті осы Негізгі Экранға тастау орындалмады."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Жасақтау үшін виджет таңдау"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Қалта атауы"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Қалтаның атауын өзгерту"</string>
+    <string name="rename_action" msgid="5559600076028658757">"Жарайды"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Өшіру"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Негізгі экранға қосу"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Қолданбалар"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Төте пернелер"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Виджеттер"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Негізгі экранда орын жоқ."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Бұл Негізгі экранда орын қалмады."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Қалаулылар науасында орын қалмады"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Бұл виджет Қалаулылар науасы үшін тым үлкен"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі жасақталды."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі алынды."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі бұрыннан бар."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Төте перне таңдау"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Қолданба таңдау"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Қолданбалар"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Негізгі"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Алып тастау"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Алмау"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Алып тастау"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Алмау"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Қолданба ақпары"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Іздеу"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Дауыс арқылы іздеу"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Қолданбалар"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Алып тастау"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Жаңартуды алмау"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Қолданбаны алып тастау"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Қолданба туралы толығырақ"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 қолданба таңдалған"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виджет таңдалған"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 қалта таңдалған"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 төте перне таңдалған"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"төте пернелерді орнату"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"төте пернелерді алып тастау"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді алу мүмкіндігін береді."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"Негізгі экрандағы параметрлер мен төте пернелерді оқу"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді оқу мүмкіндігін береді."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"Негізгі экран параметрлері мен төте пернелерін жазу"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді өзгерту мүмкіндігін береді."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Виджетті жүктеу барысында мәселе орын алды"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Бұл жүйе қолданбасы, сондықтан оны алу мүмкін емес."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Атауы жоқ қалта"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"%1$d негізгі экран"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%1$d бет, барлығы %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d негізгі экран, барлығы %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d қолданба беті, барлығы %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d виджет беті, барлығы %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Қош келдіңіз"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Өзіңізді ыңғайлы сезініңіз."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Қолданбалар мен қалталар үшін көбірек экрандар жасау"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Қолданба таңбаларын көшіру"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Бұрынғы негізгі экрандарыңыздағы таңбалар мен қалталар импортталсын ба?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ТАҢБАЛАРДЫ КӨШІРУ"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"ЖАҢАДАН БАСТАУ"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Кеңістікті реттеу"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Артқы фонды, виджеттерді және параметрлерді басқару үшін артқы шебін түртіп, мықтап ұстаңыз."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Міне, қалта."</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Осы сияқты қалта жасау үшін, қолданбаны түртіп, мықтап ұстаңыз, одан кейін екіншісінің үстінен жылжытыңыз."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"Жарайды"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Қалта ашылды, <xliff:g id="WIDTH">%1$d</xliff:g> және <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Қалтаны жабу үшін түртіңіз"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Өзгертілген атауын сақтау үшін түртіңіз"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Қалта жабылды"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Қалта атауы <xliff:g id="NAME">%1$s</xliff:g> болып өзгертілді"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Қалта: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Артқы фондар"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Параметрлер"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Күтілуде"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Жүктелуде"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Орнатылуда"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Белгісіз"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Қалп. кел-меді"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Барлығын алып тастау"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Алып тастау"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Іздеу"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Бұл қолданба орнатылмаған"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Осы белгіше үшін қолданба орнатылмаған. Оны жоюға болады немесе қолданбаны іздеп, қолмен орнатуға болады."</string>
+</resources>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index dafbdf6..bcd6060 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"ដើម"</string>
     <string name="uid_name" msgid="7820867637514617527">"កម្មវិធី​​សំខាន់​ៗ​របស់ Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"កំណត់​ផ្ទាំង​រូបភាព"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"បាន​ជ្រើស %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"បាន​ជ្រើស %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"បាន​ជ្រើស %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"ផ្ទាំង​រូបភាព %1$d នៃ %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"​បាន​ជ្រើស <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"លុប"</string>
-    <string name="pick_image" msgid="1272073934062909527">"ជ្រើស​យក​រូបភាព"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"ផ្ទាំង​រូបភាព"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"ច្រឹប​ផ្ទាំង​រូបភាព"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"បាន​បិទ​កម្មវិធី​ដែល​បាន​ទាញ​យក​ក្នុង​របៀប​សុវត្ថិភាព"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ​ Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​រស់​អ្នក​ទៀត​ទេ។"</string>
     <string name="out_of_space" msgid="4691004494942118364">"គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​នេះ​ទៀត​ទេ។"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"គ្មាន​បន្ទប់​នៅ​ក្នុង​មជ្ឈមណ្ឌល​ទៀត​ទេ។"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"ធាតុ​ក្រាហ្វិក​នេះ​ធំ​ពេក​សម្រាប់​មជ្ឈមណ្ឌល។"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"គ្មាន​បន្ទប់​​ក្នុង​ថាស​និយម​ប្រើ"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ធាតុ​ក្រាហ្វិក​នេះ​ធំ​ពេក​សម្រាប់​ថាស​និយម​ប្រើ"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"បាន​បង្កើត​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" ។"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"បាន​លុប​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" ។"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"មាន​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" រួច​ហើយ។"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"សរសេរ​ការ​កំណត់ ​និង​ផ្លូវកាត់​​លើ​អេក្រង់​ដើម"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"អនុញ្ញាត​ឲ្យ​កម្មវិធី​ប្ដូរ​ការ​កំណត់ និង​ផ្លូវ​កាត់​ក្នុង​អេក្រង់​ដើម។"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"បញ្ហា​ក្នុង​ការ​ផ្ទុក​ធាតុ​​ក្រាហ្វិក"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"រៀបចំ"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"នេះ​​​ជា​កម្មវិធី​ប្រព័ន្ធ មិន​អាច​លុប​បាន​ទេ។"</string>
     <string name="dream_name" msgid="1530253749244328964">"កម្មវិធី​ចាប់ផ្ដើម​រ៉ូកែត"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"ថត​គ្មាន​ឈ្មោះ"</string>
@@ -96,7 +86,7 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"អេក្រង់​ដើម %1$d នៃ %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"ទំព័រ​កម្មវិធី %1$d នៃ %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ទំព័រ​ធាតុ​ក្រាហ្វិក ​%1$d នៃ %2$d"</string>
-    <string name="first_run_cling_title" msgid="2459738000155917941">"សូម​ស្វាគមន៍"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"សូម​ស្វាគមន៍​"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"ធ្វើ​ដោយ​ខ្លួន​ឯង​នៅ​លើ​អេក្រង់​ដើម។"</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ចាប់ផ្ដើម​ធ្វើ​ឲ្យ​ស្រស់"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"រៀបចំ​ចន្លោះ​របស់​អ្នក"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"ប៉ះ &amp; សង្កត់​លើ​ផ្ទៃ​ខាង​ក្រោម ដើម្បី​គ្រប់គ្រង​ផ្ទាំង​រូបភាព, ធាតុ​ក្រាហ្វិក និង​ការ​កំណត់។"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"ជ្រើស​កម្មវិធី​មួយ​ចំនួន"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"ប៉ះ​ &amp; សង្កត់​វា ដើម្បី​បន្ថែម​កម្មវិធី​ទៅ​​​អេក្រង់​ដើម​របស់​អ្នក"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ផ្ទាំងរូបភាព,ធាតុក្រាហ្វិក &amp; ការកំណត់"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ប៉ះ &amp; សង្កត់​ផ្ទៃ​ខាង​ក្រោយ​ដើម្បី​ប្ដូរ​តាម​​តម្រូវ​ការ"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"យល់​ហើយ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"នេះ​ជា​ថត"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"ដើម្បី​បង្កើត​មួយ​ដូច​នេះ ប៉ះ &amp; សង្កត់​​លើ​កម្មវិធី បន្ទាប់​មក​ផ្លាស់ទី​វា​ទៅ​លើ​ធាតុ​មួយ​ផ្សេង​ទៀត។"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"យល់ព្រម"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"បាន​បិទ​ថត"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"បាន​ប្ដូរ​ឈ្មោះ​ថត​ជា <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ផ្ទាំង​រូបភាព"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"ការកំណត់"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"រង់ចាំ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"​ទាញ​យក"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ដំឡើង"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"មិន​ស្គាល់"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"មិនបាន​​ស្តា​រ"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"លុបចេញ​​​ទាំងអស់"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"លុបចេញ"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ស្វែងរក"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"មិន​បាន​ដំឡើង​កម្មវិធី​នេះ"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"មិន​បាន​ដំឡើង​កម្មវិធី​សម្រាប់​រូបតំណាង​នេះ។ អ្នក​អាច​លុប​វា ឬ​ស្វែងរក​កម្មវិធី និង​ដំឡើង​វា​ដោយ​ដៃ។"</string>
 </resources>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
new file mode 100644
index 0000000..e84ece0
--- /dev/null
+++ b/res/values-kn-rIN/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"ಲಾಂಚರ್3"</string>
+    <string name="home" msgid="7658288663002113681">"ಮುಖಪುಟ"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android Core ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾದ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"ವಿಜೆಟ್‌ಗಳು"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"ವಿಜೆಟ್‌ಗಳು"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"ಸ್ಮರಣೆ ತೋರಿಸು"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"ವಿಜೆಟ್ ಅನ್ನು ಆರಿಸಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ &amp; ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
+    <string name="market" msgid="2619650989819296998">"ಶಾಪ್‌"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಐಟಂ ಅನ್ನು ಬಿಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ರಚಿಸಲು ವಿಜೆಟ್‌ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"ಫೋಲ್ಡರ್ ಹೆಸರು"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"ಫೋಲ್ಡರ್ ಅನ್ನು ಮರುಹೆಸರಿಸಿ"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ಸರಿ"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"ರದ್ದುಮಾಡು"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು"</string>
+    <string name="group_applications" msgid="3797214114206693605">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"ವಿಜೆಟ್‌ಗಳು"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"ನಿಮ್ಮ ಮುಖಪುಟದ ಪರದೆಗಳಲ್ಲಿ ಯಾವುದೇ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇನಲ್ಲಿ ಹೆಚ್ಚಿನ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇಗೆ ಈ ವಿಜೆಟ್‌ ತುಂಬಾ ದೊಡ್ಡದಾಗಿದೆ"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಅನ್ನು ರಚಿಸಲಾಗಿದೆ."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"ಶಾರ್ಟ್‌ಕಟ್‌ ಆರಿಸಿ"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"ಮುಖಪುಟ"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ತೆಗೆದುಹಾಕು"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ಅಸ್ಥಾಪಿಸು"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"ತೆಗೆದುಹಾಕು"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ಅಸ್ಥಾಪಿಸು"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"ಹುಡುಕು"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"ಧ್ವನಿ ಹುಡುಕಾಟ"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"ತೆಗೆದುಹಾಕು"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ನವೀಕರಣವನ್ನು ಅಸ್ಥಾಪಿಸು"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ಥಾಪಿಸು"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"ಅಪ್ಲಿಕೇಶನ್ ವಿವರಗಳು"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ವಿಜೆಟ್‌ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ಫೋಲ್ಡರ್‌ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ಶಾರ್ಟ್‌ಕಟ್‌ ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಅಸ್ಥಾಪಿಸಿ"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಿ"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬರೆಯಿರಿ"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"ವಿಜೆಟ್ ಲೋಡ್‌ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="dream_name" msgid="1530253749244328964">"ರಾಕೆಟ್ ಲಾಂಚರ್"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"ಮುಖಪುಟದ ಪರದೆ %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$d ರಲ್ಲಿ %1$d ಪುಟ"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d ರಲ್ಲಿ %1$d ಮುಖಪುಟದ ಪರದೆ"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d ರಲ್ಲಿ %1$d ಅಪ್ಲಿಕೇಶನ್ ಪುಟ"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d ರಲ್ಲಿ %1$d ವಿಜೆಟ್‌ಗಳ ಪುಟ"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"ಸುಸ್ವಾಗತ"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"ನಿಮ್ಮ ಮನೆಯಂತೆ ಭಾವಿಸಿ."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಫೋಲ್ಡರ್‌ಗಳಿಗಾಗಿ ಇನ್ನಷ್ಟು ಪರದೆಗಳನ್ನು ರಚಿಸಿ"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"ಅಪ್ಲಿಕೇಶನ್‌ ಐಕಾನ್‌ ನಕಲಿಸು"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"ನಿಮ್ಮ ಹಳೆಯ ಮುಖಪುಟದ ಪರದೆಗಳಿಂದ ಐಕಾನ್‌ಗಳು ಮತ್ತು ಫೋಲ್ಡರ್‌ಗಳನ್ನು ಆಮದು ಮಾಡಿಕೊಳ್ಳುವುದೇ?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ಐಕಾನ್‌ಗಳನ್ನು ನಕಲಿಸು"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"ಹೊಸದಾಗಿ ಪ್ರಾರಂಭಿಸು"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ವ್ಯವಸ್ಥಿತಗೊಳಿಸಿ"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"ವಾಲ್‌ಪೇಪರ್‌, ವಿಜೆಟ್‌ಗಳು ಮತ್ತು ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಹಿನ್ನೆಲೆಯನ್ನು ಸ್ಪರ್ಶಿಸಿ &amp; ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"ಇಲ್ಲೊಂದು ಫೋಲ್ಡರ್ ಇದೆ"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ಈ ರೀತಿ ರಚಿಸಲು, ಸ್ಪರ್ಶಿಸಿ &amp; ಆಪ್‌ ಹಿಡಿದುಕೊಂಡು ಮತ್ತೊಂದರ ಮೇಲೆ ಸರಿಸಿ."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ಸರಿ"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ಫೋಲ್ಡರ್ ತೆರೆಯಲಾಗಿದೆ, <xliff:g id="WIDTH">%1$d</xliff:g> ಬೈ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"ಫೋಲ್ಡರ್‌ ಮುಚ್ಚಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"ಮರುಹೆಸರನ್ನು ಉಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ಫೋಲ್ಡರ್ ಮುಚ್ಚಿದೆ"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"ಫೋಲ್ಡರ್‌ ಅನ್ನು <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಮರುಹೆಸರಿಸಲಾಗಿದೆ"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"ಫೋಲ್ಡರ್: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"ವಿಜೆಟ್‌ಗಳು"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"ಅಜ್ಞಾತ"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ಇನ್ನೂ ಪುನಃಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"ಎಲ್ಲವನ್ನೂ ತೆಗೆದುಹಾಕಿ"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ಹುಡುಕು"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ಈ ಐಕಾನ್ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ. ನೀವು ಅದನ್ನು ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಹುಡುಕಬಹುದು ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅದನ್ನು ಸ್ಥಾಪಿಸಬಹುದು."</string>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 9ef40e1..41c854e 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"홈"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android 핵심 앱"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"배경화면 설정"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d개 선택됨"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d개 선택됨"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d개 선택됨"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"배경화면 %1$d/%2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> 선택함"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"삭제"</string>
-    <string name="pick_image" msgid="1272073934062909527">"이미지 선택"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"배경화면"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"배경화면 잘라내기"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"앱이 설치되지 않았습니다."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"다운로드한 앱은 안전 모드에서 사용할 수 없습니다."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"위젯"</string>
     <string name="widget_adder" msgid="3201040140710381657">"위젯"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"위젯"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"홈 화면에 더 이상 공간이 없습니다."</string>
     <string name="out_of_space" msgid="4691004494942118364">"홈 화면에 더 이상 공간이 없습니다."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"즐겨찾는 앱 모음에 더 이상 빈 공간이 없습니다."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"이 위젯은 너무 커서 즐겨찾는 앱 모음에 들어갈 수 없습니다."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"즐겨찾기 트레이에 더 이상 공간이 없습니다."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"위젯이 너무 커서 즐겨찾기 트레이에 들어갈 수 없습니다."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 생성되었습니다."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 삭제되었습니다."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 이미 있습니다."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"홈 설정 및 바로가기 쓰기"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"앱이 홈에 있는 설정 및 바로가기를 변경할 수 있도록 합니다."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"위젯을 로드하는 중 문제가 발생했습니다."</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"설정"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"시스템 앱은 제거할 수 없습니다."</string>
     <string name="dream_name" msgid="1530253749244328964">"로켓 실행기"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"이름이 없는 폴더"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"새로 시작"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"공간 관리하기"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"배경화면, 위젯, 설정을 관리하려면 백그라운드를 길게 터치합니다."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"앱 선택하기"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"홈 화면에 앱을 추가하려면 길게 터치합니다."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"배경화면, 위젯, 설정"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"백그라운드를 길게 터치하여 맞춤설정합니다."</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"확인"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"폴더"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"폴더를 만들려면 앱을 길게 터치한 다음 다른 앱 위에 올려 놓으세요."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"확인"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"폴더 닫음"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"폴더 이름 변경: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"폴더: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"위젯"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"배경화면"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"설정"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"대기 중"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"다운로드 중"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"설치 중"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"복원되지 않음"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"모두 삭제"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"삭제"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"검색"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"이 앱이 설치되어 있지 않음"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"이 아이콘의 앱이 설치되어 있지 않습니다. 아이콘을 삭제하거나 앱을 검색하여 수동으로 설치하세요."</string>
 </resources>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
new file mode 100644
index 0000000..5b50555
--- /dev/null
+++ b/res/values-ky-rKG/strings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"Үйгө"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android Core колдонмолору"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Колдонмо орнотулган эмес."</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Виджеттер"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Виджеттер"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мемди көргөзүү"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетти тандаш үчүн, басып туруңуз"</string>
+    <string name="market" msgid="2619650989819296998">"Дүкөн"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Муну бул Үй экранына ыргытуу мүмкүн эмес."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Түзүлүүчү виджетти тандаңыз"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Фолдердин аты"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Фолдердин атын өзгөртүү"</string>
+    <string name="rename_action" msgid="5559600076028658757">"OK"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Жокко чыгаруу"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Үй экранына кошуу"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Колдонмолор"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Тез чакырмалар"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Виджеттер"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Үй экрандарыңызда бош орун калган жок."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Бул Үй экранында бош орун жок."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Тандамалдар тайпасында орун калган жок"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Бул виджет Тандамалдар үчүн өтө чоң"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы түзүлдү."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы алынып салынды."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы бар."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Тез чакырма тандоо"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Колдонмо тандоо"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Колдонмолор"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Үйгө"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Алып салуу"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Чечип салуу"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Алып салуу"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Чечип салуу"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Колдонмо тууралуу"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Издөө"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Үн менен издөө"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Колдонмолор"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Алып салуу"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Жаңыртууну чечип салуу"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Колдонмону чечип салуу"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Колдонмонун кеңири маалыматтары"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 колдонмо тандалды"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виджет тандалды"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 фолдер тандалды"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 тез чакырма тандалды"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"тез чакырмаларды орнотуу"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"тез чакырмаларды жок кылуу"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Колдонмого колдонуучуга кайрылбастан тез чакырмаларды жок кылууга уруксат берет."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"Үйдүн тууралоолорун жана тез чакырмаларын окуу"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын окууга уруксат берет."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"Үйдүн тууралоолорун жана тез чакырмаларын жазуу"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын өзгөртүүгө уруксат берет."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Виджетти жүктөөдө маселе бар"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Бул системдик колдонмо жана аны чечкенге болбойт."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Аты жок фолдер"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"Үй экраны %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$d ичинен %1$d барак"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Үй экраны %2$d ичинен %1$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Колдонмолор барагы %2$d ичинен %1$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Виджеттер барагы %2$d ичинен %1$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Кош келиңиз"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Өзүңүздү үйүңүздөгүдөй эркин сезиңиз."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Колдонмолор жана фолдерлер үчүн кошумча экрандарды түзүңүз"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Колдонмоңуздун сүрөтчөлөрүн көчүрүү"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Эски үй экрандарыңыздан сүрөтчөлөр жана фолдерлер импорттолсунбу?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"СҮРӨТЧӨЛӨРДҮ КӨЧҮРҮҮ"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"ТАЗАСЫН БАШТОО"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Өз мейкиндигиңизди уюштуруңуз"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Тушкагаздарды, виджеттерди жана тууралоолорду башкаруу үчүн фонду басып туруңуз."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Мынакей фолдер"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Башкасын түзүш үчүн колдонмону басып туруп, башканын жанына жылдырыңыз."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Фолдер ачылды, туурасы <xliff:g id="WIDTH">%1$d</xliff:g>, бийиктиги <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Фолдерди жабыш үчүн тийиңиз"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Тийип, аттын өзгөртүлүшүн сактаңыз"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Фолдер жабык"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Фолдердин аты <xliff:g id="NAME">%1$s</xliff:g> деп өзгөртүлдү"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Тууралоолор"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Күтүүдө"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Жүктөлп алнууда"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Орнотулууда"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Белгисиз"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Калыбн келт. жок"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Баарын алып салуу"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Алып салуу"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Издөө"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Бул колдонмо орнотулган эмес"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Бул сүрөтчөнүн колдонмосу орнотулган эмес. Аны алып салсаңыз же колдонмону издеп, кол менен орнотсоңуз болот."</string>
+</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 07d9279..1b34181 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -23,6 +23,4 @@
     <dimen name="apps_customize_tab_bar_height">42dp</dimen>
     <integer name="apps_customize_widget_cell_count_x">3</integer>
     <integer name="apps_customize_widget_cell_count_y">2</integer>
-    <integer name="apps_customize_cling_focused_x">2</integer>
-    <integer name="apps_customize_cling_focused_y">1</integer>
 </resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index fa3801d..87a7444 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -19,10 +19,6 @@
 
 <resources>
 <!-- Search Bar -->
-    <style name="QSBBar">
-    </style>
-    <style name="SearchDropTargetBar">
-    </style>
     <style name="SearchButton">
     </style>
     <style name="DropTargetButtonContainer">
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 2fb2df0..1d953ff 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"ໜ້າຫຼັກ"</string>
     <string name="uid_name" msgid="7820867637514617527">"ແອັບພລິເຄຊັນຫຼັກຂອງ Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"ຕັ້ງເປັນພາບພື້ນຫຼັງ"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"ເລືອກ %1$d ລາຍການແລ້ວ"</item>
-    <item quantity="one" msgid="142482526010824029">"ເລືອກ %1$d ລາຍການແລ້ວ"</item>
-    <item quantity="other" msgid="1418352074806573570">"ເລືອກ %1$d ລາຍການແລ້ວ"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"ຮູບພືື້ນຫຼັງ %1$d ໃນ %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"ເລືອກແລ້ວ <xliff:g id="LABEL">%1$s</xliff:g> ອັນ"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"ລຶບ"</string>
-    <string name="pick_image" msgid="1272073934062909527">"ເລືອກຮູບ"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"ພາບພື້ນຫຼັງ"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"ຕັດຮູບພື້ນຫຼັງ"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ແອັບຯ​ທີ່​ດາວ​ໂຫລດ​ແລ້ວ​ຖືກ​ປິດ​ການ​ນຳ​ໃຊ້​ໃນ Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"ວິດເຈັດ"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
@@ -47,15 +36,15 @@
     <string name="rename_folder_label" msgid="3727762225964550653">"ຊື່ໂຟນເດີ"</string>
     <string name="rename_folder_title" msgid="3771389277707820891">"ປ່ຽນຊື່ໂຟນເດີ"</string>
     <string name="rename_action" msgid="5559600076028658757">"ຕົກລົງ"</string>
-    <string name="cancel_action" msgid="7009134900002915310">"ຍົກ​ເລີກ"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"ຍົກ​ເລີກ​"</string>
     <string name="menu_item_add_item" msgid="1264911265836810421">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
     <string name="group_applications" msgid="3797214114206693605">"ແອັບຯ"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"ທາງລັດ"</string>
     <string name="group_widgets" msgid="1569030723286851002">"ວິດເຈັດ"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກຂອງທ່ານ."</string>
     <string name="out_of_space" msgid="4691004494942118364">"ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກນີ້."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"ບໍ່ມີຫ້ອງຫວ່າງໃນ hotseat ແລ້ວ."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"ວິດເຈັດ ມີຂະໜາດໃຫຍ່ເກີນໄປສຳລັບ hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"ບໍ່ມີບ່ອນຫວ່າງໃນຖາດສຳລັບເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ວິດເຈັດນີ້ໃຫຍ່ເກີນໄປທີ່ຈະເກັບໄວ້ໃນຖາດເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ຖືກສ້າງແລ້ວ."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ຖືກລຶບແລ້ວ."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ມີຢູ່ແລ້ວ."</string>
@@ -64,9 +53,9 @@
     <string name="all_apps_button_label" msgid="9110807029020582876">"ແອັບຯ"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"ໜ້າຫຼັກ"</string>
     <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ລຶບ"</string>
-    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ຖອນການຕິດຕັ້ງ"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ຖອນ​ການ​ຕິດ​ຕັ້ງ"</string>
     <string name="delete_target_label" msgid="1822697352535677073">"ລຶບ"</string>
-    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ຖອນການຕິດຕັ້ງ"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ຖອນ​ການ​ຕິດ​ຕັ້ງ"</string>
     <string name="info_target_label" msgid="8053346143994679532">"ຂໍ້ມູນແອັບຯ"</string>
     <string name="accessibility_search_button" msgid="1628520399424565142">"ຊອກຫາ"</string>
     <string name="accessibility_voice_search_button" msgid="4637324840434406584">"ຊອກຫາດ້ວຍສຽງ"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"ຂຽນການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວ ປ່ຽນການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"ມີບັນຫາໃນການໂຫລດວິດເຈັດ"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"ຕິດຕັ້ງ"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"ນີ້ແມ່ນແອັບຯຂອງລະບົບ ແລະບໍ່ສາມາດຖອນການຕິດຕັ້ງອອກໄດ້."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່"</string>
@@ -107,10 +97,11 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ເລີ່ມຕົ້ນໃໝ່"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"ຈັດການພື້ນທີ່ຂອງທ່ານ"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"ແຕະຄ້າງໄວ້ທີ່ພາບພື້ນຫຼັງເພື່ອຈັດການພາບພື້ນຫຼັງ, ວິດເຈັດແລະການຕັ້ງຄ່າ."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"ເລືອກແອັບຯ"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"ເພື່ອເພີ່ມແອັບຯໃສ່ໜ້າຈໍຫຼັກຂອງທ່ານ, ໃຫ້ແຕະຄ້າງໄວ້."</string>
-    <string name="folder_cling_title" msgid="3894908818693254164">"ນີ້ແມ່ນໂຟນເດີ່"</string>
-    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ເພື່ອສ້າງອັນໃໝ່ແບບນີ້, ແຕະຄ້າງໄວ້ທີ່ແອັບຯ ແລ້ວຍ້າຍມັນໄປຫາໂຕອື່ນ."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"​ຮູບ​ພື້ນຫຼັງ, ວິດເຈັດ, &amp; ​ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ແຕະທີ່​ພາບ​ພື້ນ​ຫລັງ​ຄ້າງ​ໄວ້​ເພື່ອ​ປັບ​ແຕ່ງ"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ເຂົ້າໃຈແລ້ວ"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"ນີ້ແມ່ນໂຟນເດີ"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ເພື່ອ​ສ້າງ​ອັນໃໝ່​ແບບນີ້ ໃຫ້​ແຕະ​ຄ້າງ​ໄວ້​ທີ່​ແອັບຯ​ທີ່​ຕ້ອງການ​ຍ້າຍ​ແລ້ວ​ລາກ​ມັນ​ໄປ​ຫາ​ໂຕ​ອື່ນ."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"ຕົກລົງ"</string>
     <string name="folder_opened" msgid="94695026776264709">"ເປີດໂຟນເດີແລ້ວ, <xliff:g id="WIDTH">%1$d</xliff:g> ຄູນ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"ສຳພັດເພື່ອປິດໂຟນເດີ"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"ປິດໂຟນເດີແລ້ວ"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"ປ່ຽນຊື່ໂຟນເດີເປັນ <xliff:g id="NAME">%1$s</xliff:g> ແລ້ວ"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"ວິດເຈັດ"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"ການຕັ້ງຄ່າ"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"ກຳ​ລັງ​ລໍ​ຖ້າ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ກຳລັງດາວໂຫລດ"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"​ກຳ​ລັງ​ຕິດ​ຕັ້ງ"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"​ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ບໍ່​ໄດ້​ກູ້​ຂໍ້ມູນ​ມາ​ເທື່ອ"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"ລຶບ​ທັງ​ໝົດ"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ລຶບ​"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ຊອກຫາ"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ແອັບຯ​ນີ້​ຍັງ​ບໍ່​ໄດ້​ຕິດ​ຕັ້ງ​ເທື່ອ"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"​ແອັບຯ​ສຳ​ລັບ​ໄອ​ຄອນ​ນີ້​ຍັງ​ບໍ່ໄດ້​ຕິດ​ຕັ້ງ​ເທື່ອ. ທ່ານ​ສາ​ມາດ​ລຶບ​ມັນ​ອອກ ຫຼື​ຊອກ​ຫາ​ແອັບຯ ແລ້ວ​ຕິດ​ຕັ້ງ​ມັນ​ໄດ້​ດ້ວຍ​ຕົນ​ເອງ."</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 89bae55..f7db792 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Pagrindinis"</string>
     <string name="uid_name" msgid="7820867637514617527">"Pagrindinės „Android“ programos"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Nustatyti ekrano foną"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Pasirinkta: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Pasirinkta: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Pasirinkta: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%1$d iš %2$d ekrano fonų"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Pasirinkta: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Ištrinti"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pasirinkti vaizdą"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Ekrano fonai"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Ekrano fono apkirpimas"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Programa neįdiegta."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Atsisiųsta programa išjungta Saugos režimu"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Valdikliai"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Valdikliai"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rodyti atmintinę"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Valdikliai"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Pagrindiniuose ekranuose vietos nebėra."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Šiame pagrindiniame ekrane vietos nebėra."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Įtvirtintojoje srityje nebėra vietos."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Šis valdiklis įtvirtintajai sričiai per didelis."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Mėgstamiausių dėkle nebėra vietos"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Mėgstamiausių dėklui šis valdiklis per didelis."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ sukurtas."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ pašalintas."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ jau yra."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"rašyti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Programai leidžiama keisti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema įkeliant valdiklį"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Sąranka"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Tai sistemos programa ir jos negalima pašalinti."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Aplankas be pavadinimo"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"PRADĖTI IŠ NAUJO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Tvarkykite savo vietą"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Palieskite ir laikykite foną, jei norite tvarkyti ekrano foną, valdiklius ir nustatymus."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Pasirinkite kelias programas"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Jei norite prie pagrindinio ekrano pridėti programą, palieskite ją ir laikykite."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ekrano fonai, valdikliai ir nustatymai"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Jei norite tinkinti, palieskite ir palaikykite foną"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SUPRATAU"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Štai aplankas"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Kad sukurtumėte tokį patį, palieskite ir laikykite programą, tada perkelkite ją virš kitos programos."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Gerai"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Aplankas uždarytas"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Aplankas pervardytas kaip „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Aplankas: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Valdikliai"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Ekrano fonai"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Nustatymai"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Laukiama"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Atsisiunčiama"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Diegiama"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Nežinoma"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Neatkurta"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Pašalinti viską"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Pašalinti"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Ieškoti"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ši programa neįdiegta"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Šios piktogramos programa neįdiegta. Galite ją pašalinti arba bandyti ieškoti programos ir ją įdiegti patys."</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index b4e7ee9..75eb054 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Sākums"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android pamatlietotnes"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Iestatīt fona tapeti"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Atlasīti: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Atlasīti: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Atlasīti: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%1$d. fona tapete no %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Atlasīts: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Dzēst"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Izvēlēties attēlu"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Fona tapetes"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Apgriezt fona tapeti"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Lietotne nav instalēta."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Lejupielādētā lietotne ir atspējota drošajā režīmā."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Logrīki"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Logrīki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rādīt atmiņu"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Logrīki"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Sākuma ekrānos vairs nav vietas."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Šajā sākuma ekrānā vairs nav vietas."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Režīmā “hotseat” vairs nav vietas."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Šis logrīks ir pārāk liels režīmam “hotseat”."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Izlases joslā vairs nav vietas."</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Šis logrīks ir pārāk liels izlases joslai."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Tika izveidota saīsne “<xliff:g id="NAME">%s</xliff:g>”."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Tika noņemta saīsne “<xliff:g id="NAME">%s</xliff:g>”."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Saīsne “<xliff:g id="NAME">%s</xliff:g>” jau pastāv."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"rakstīt sākuma ekrāna iestatījumus un saīsnes"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ļauj lietotnei mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Ielādējot logrīku, radās problēma."</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Notiek iestatīšana"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Mape bez nosaukuma"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"SĀKT NO SĀKUMA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Kārtojiet savu darbvietu"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Pieskarieties fonam un turiet to, lai pārvaldītu fona tapeti, logrīkus un iestatījumus."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Izvēlieties dažas lietotnes"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Lai sākuma ekrānam pievienotu lietotni, pieskarieties tai un turiet to."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fona tapetes, logrīki un iestatījumi"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Lai pielāgotu, pieskarieties fonam un turiet to nospiestu."</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SAPRATU!"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Lūk, mape!"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Lai izveidotu tādu pašu, pieskarieties lietotnei un turiet to, pēc tam pārvietojiet to virs citas lietotnes."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Labi"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mape aizvērta"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mape pārdēvēta par: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mape: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Logrīki"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fona tapetes"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Iestatījumi"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Gaida"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Lejupielādē"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalē"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Nezināma"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nav atjaunota"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Noņemt visas"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Noņemt"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Meklēt"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Šī lietotne nav instalēta"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Šai ikonai paredzētā lietotne nav instalēta. Varat noņemt ikonu vai meklēt lietotni un instalēt to manuāli."</string>
 </resources>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
new file mode 100644
index 0000000..0d77571
--- /dev/null
+++ b/res/values-mk-rMK/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"Почетна страница"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Основни апликации на Android"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Апликацијата не е инсталирана."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Преземената апликација е оневозможена во безбеден режим"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи „Мени“"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Допри и задржи за да се избере виџетот."</string>
+    <string name="market" msgid="2619650989819296998">"Продавница"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Не можеше да се спушти елемент на овој екран на почетната страница."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избери виџет за да се создаде"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Име на папка"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Преименувај папка"</string>
+    <string name="rename_action" msgid="5559600076028658757">"Во ред"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Откажи"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Додај во екран на почетна страница"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Апликации"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Кратенки"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Виџети"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Нема повеќе простор на вашите екрани на почетна страница."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Нема повеќе простор на овој екран на почетната страница."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Нема повеќе простор на лентата „Омилени“"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Овој виџет е премногу голем за лентата „Омилени“"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ е создадена."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ е отстранета."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ веќе постои."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Избери кратенка"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Избери апликација"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Апликации"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Почетна страница"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Отстрани"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Деинсталирај"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Отстрани"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Деинсталирај"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Информации за апликацијата"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Пребарај"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Гласовно пребарување"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Апликации"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"Отстрани"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Деинсталирај ажурирање"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Деинсталирај апликација"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Детали за апликација"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 апликација е избрана"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виџет е избран"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 папка е избрана"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 кратенка е избрана"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирај кратенки"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Овозможува апликацијата да додава кратенки без интервенција на корисникот."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"деинсталирај кратенки"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Овозможува апликацијата да ги отстрани кратенките без интервенција на корисникот."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"прочитај подесувања и кратенки на почетна страница"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"напиши подесувања и кратенки на почетна страница"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Проблем при вчитувањето на виџетот"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ова е системска апликација и не може да се деинсталира."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Неименувана папка"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"Екран на почетна страница %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"Страница %1$d од %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Екран на почетна страница %1$d од %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Страница на апликации %1$d од %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Страница на виџети %1$d од %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Добредојдовте"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"Чувствувајте се како дома."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Создади повеќе екрани за апликации и папки"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Копирај икони за апликација"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Увези икони и папки од старите екрани на почетната страница?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРАЈ ИКОНИ"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"СТАРТУВАЈ ОД ПОЧЕТОК"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Организирајте го вашиот простор"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Допри и задржи ја заднината за управување со тапети, виџети и подесувања."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Еве папка"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"За да создадете ваква, допрете и држете ја апликацијата, а потоа поместете ја врз другата."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"Во ред"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Отворена е папка, <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Допри за да се затвори папката"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Допри за да се зачува преименувањето"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Папката е затворена"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Папката е преименувана во <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Подесувања"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"На чекање"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Се презема"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Се инсталира"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Не е обновено"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Отстрани ги сите"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Барај"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Апликацијата не е инсталирана"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Апликацијата за оваа икона не е инсталирана. Може да ја отстраните или да се обидете да ја најдете апликацијата и да ја инсталирате рачно."</string>
+</resources>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
new file mode 100644
index 0000000..32329f1
--- /dev/null
+++ b/res/values-ml-rIN/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"ഹോം"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android Core അപ്ലിക്കേഷനുകൾ"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"അപ്ലിക്കേഷൻ ഇൻസ്‌റ്റാളുചെ‌യ്‌തിട്ടില്ല."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ഡൗൺലോഡുചെയ്‌ത അപ്ലിക്കേഷൻ സുരക്ഷാ മോഡിൽ പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"വിജറ്റുകൾ"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"വിജറ്റുകൾ"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"മെമ്മറി കാണിക്കുക"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"ഒരു വിജറ്റ് ചേർക്കുന്നതിന് അത് സ്‌പർശിച്ച് പിടിക്കുക."</string>
+    <string name="market" msgid="2619650989819296998">"ഷോപ്പുചെയ്യുക"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"ഹോം സ്‌ക്രീനിൽ ഇനം വലിച്ചിടാനായില്ല."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"സൃഷ്‌ടിക്കുന്നതിന് വിജറ്റ് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"ഫോൾഡറിന്റെ പേര്"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"ഫോൾഡറിന്റെ പേരുമാറ്റുക"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ശരി"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"റദ്ദാക്കുക"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"ഹോം സ്ക്രീനിൽ ചേർക്കുക"</string>
+    <string name="group_applications" msgid="3797214114206693605">"അപ്ലിക്കേഷനുകൾ"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"കുറുക്കുവഴികൾ"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"വിജറ്റുകൾ"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"നിങ്ങളുടെ ഹോം സ്‌ക്രീനുകളിൽ സ്ഥലമില്ല."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"ഈ ഹോം സ്‌ക്രീനിൽ ഒഴിവൊന്നുമില്ല."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"പ്രിയപ്പെട്ടവയുടെ ട്രേയിൽ ഒഴിവൊന്നുമില്ല"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ഈ വിജറ്റ് പ്രിയപ്പെട്ടവയുടെ ട്രേയിൽ ഉൾക്കൊള്ളിക്കാവുന്നതിലും വളരെ വലുതാണ്"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" സൃഷ്‌ടിച്ചു."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" നീക്കംചെയ്‌തു."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" ഇതിനകം നിലവിലുണ്ട്."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"കുറുക്കുവഴി തിരഞ്ഞെടുക്കുക"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"അപ്ലിക്കേഷൻ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"അപ്ലിക്കേഷനുകൾ"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"ഹോം"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"നീക്കംചെയ്യുക"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"അണ്‍ഇസ്റ്റാളുചെയ്യുക"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"നീക്കംചെയ്യുക"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"അണ്‍ഇസ്റ്റാളുചെയ്യുക"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"അപ്ലിക്കേഷൻ വിവരം"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"തിരയുക"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"വോയ്‌സ് തിരയൽ"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"അപ്ലിക്കേഷനുകൾ"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"നീക്കംചെയ്യുക"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"അപ്‌ഡേറ്റ് അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"അപ്ലിക്കേഷൻ അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"അപ്ലിക്കേഷൻ വിശദാംശങ്ങൾ"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"ഒരു അപ്ലിക്കേഷൻ തിരഞ്ഞെടുത്തു"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"ഒരു വിജറ്റ് തിരഞ്ഞെടുത്തു"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"ഒരു ഫോൾഡർ തിരഞ്ഞെടുത്തു"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"ഒരു കുറുക്കുവഴി തിരഞ്ഞെടുത്തു"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"കുറുക്കുവഴികൾ അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ നീക്കംചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റൈറ്റുചെയ്യുക"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും മാറ്റാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"വിജറ്റ് ലോഡുചെയ്യുന്നതിൽ പ്രശ്നമുണ്ട്"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"ഇതൊരു സിസ്‌റ്റം അപ്ലിക്കേഷനായതിനാൽ അൺഇൻസ്‌റ്റാളുചെയ്യാനാവില്ല."</string>
+    <string name="dream_name" msgid="1530253749244328964">"റോക്കറ്റ് ലോഞ്ചർ"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"പേരുനൽകാത്ത ഫോൾഡർ"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"ഹോം സ്‌ക്രീൻ %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"പേജ് %1$d / %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"ഹോം സ്‌ക്രീൻ %1$d / %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"അപ്ലിക്കേഷനുകളുടെ പേജ് %1$d / %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"വിജറ്റുകളുടെ പേജ് %1$d / %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"സ്വാഗതം"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"ഹോം നിങ്ങളുടേതാക്കി മാറ്റുക."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"അപ്ലിക്കേഷനുകൾക്കും ഫോൾഡറുകൾക്കും വേണ്ടി കൂടുതൽ സ്‌ക്രീനുകൾ സൃഷ്‌ടിക്കുക"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"നിങ്ങളുടെ അപ്ലിക്കേഷൻ ഐക്കണുകൾ പകർത്തുക"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"നിങ്ങളുടെ പഴയ ഹോം സ്ക്രീനുകളിൽ നിന്ന് ഐക്കണുകളും ഫോൾഡറുകളും ഇമ്പോർട്ടുചെയ്യണോ?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ഐക്കണുകൾ പകർത്തുക"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"പുതുതായി ആരംഭിക്കുക"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"നിങ്ങളുടെ ഇടം ഓർഗനൈസുചെയ്യുക"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"വാൾപേപ്പർ, വിജറ്റുകൾ, ക്രമീകരണങ്ങൾ എന്നിവ നിയന്ത്രിക്കുന്നതിന് പശ്ചാത്തലം സ്‌പർശിച്ച് പിടിക്കുക."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"ഇവിടെയൊരു ഫോൾഡർ ഉണ്ട്"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ഇതുപോലൊന്ന് സൃഷ്‌ടിക്കുന്നതിന്, ഒരു അപ്ലിക്കേഷൻ സ്‌പർശിച്ച് പിടിച്ചുകൊണ്ട് അത് മറ്റൊന്നിലേക്ക് നീക്കുക."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ശരി"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ഫോൾഡർ തുറന്നു, <xliff:g id="WIDTH">%1$d</xliff:g> / <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"ഫോൾഡർ അടയ്ക്കാൻ സ്‌പർശിക്കുക"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"പേരുമാറ്റം സംരക്ഷിക്കുന്നതിന് സ്‌പർശിക്കുക"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ഫോൾഡർ അടച്ചു"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"ഫോൾഡറിന്റെ പേര് <xliff:g id="NAME">%1$s</xliff:g> എന്നായി മാറ്റി"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"ഫോൾഡർ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"വിജറ്റുകൾ"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"വാൾപേപ്പറുകൾ"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"ക്രമീകരണങ്ങൾ"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"കാത്തിരിക്കുന്നു"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ഡൗൺലോഡുചെയ്യുന്നു"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"പുനഃസ്ഥാപിച്ചിട്ടില്ല"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"എല്ലാം നീക്കം ചെയ്യുക"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"തിരയുക"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തിട്ടില്ല"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വമേധയാ ഇൻസ്റ്റാളുചെയ്യുക."</string>
+</resources>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index 13b5cd4..34fb794 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Нүүр"</string>
     <string name="uid_name" msgid="7820867637514617527">"Андройд үндсэн апп"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Ханын зургийг тохируулах"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d сонгогдсон"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d сонгогдсон"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d сонгогдсон"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"%2$d ханын цаасны %1$d нь"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> сонгогдсон"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Устгах"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Зураг сонгох"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Ханын зураг"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Ханын зургийг тайрах"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Апп суугаагүй байна."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Татаж авсан апп-г Аюулгүй горим дотроос идэвхгүйжүүлсэн"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Виджет"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виджет"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Виджет"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Таны Нүүр дэлгэц зайгүй."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Энэ Нүүр дэлгэц зайгүй."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Суурь зайгүй."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Энэ виджет сууринд хэт томдож байна."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"\"Дуртай\" трей дээр өөр зай байхгүй байна"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Энэ виджет трей дээр хэт томдож байна"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол үүсэв."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол устгагдав."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол өмнө үүссэн байна."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"Нүүрний тохиргоо болон товчлолыг бичих"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Апп нь Нүүрэндэх товчлол болон тохиргоог өөрчилж чадна."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Виджет ачаалахад асуудал гарав"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Тохируулга"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Энэ апп нь системийн апп ба устгах боломжгүй."</string>
     <string name="dream_name" msgid="1530253749244328964">"Пуужин хөөргөгч"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Нэргүй фолдер"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ШИНЭЭР ЭХЛЭХ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Өөрийнхөө зайг тохируулаарай"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Арын дэвсгэр дээр хүрээд &amp; дарснаар ханын зураг, виджет болон тохиргоог өөрчилж болно."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Апп сонгоно уу"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Нүүр дэлгэцэнд апп нэмэх бол хүрээд барина уу."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Дэвсгэр зураг, виджет, &amp; тохиргоо"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Тааруулахын тулд арын дэлгэцэнд хүрээд &amp; барина уу"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"Ойлголоо"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Фолдер энд байна"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Үүнтэй адилханыг үүсгэхийн тулд апп дээр хүрч &amp; бариад нөгөөхийн дээр зөөнө үү."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Тийм"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Фолдер хаагдав"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Фолдерын нэр <xliff:g id="NAME">%1$s</xliff:g> болов"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Виджет"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Ханын зураг"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Тохиргоо"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Хүлээж байна"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Татаж авч байна"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Суулгаж байна"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Тодорхойгүй"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Сэргээгээгүй"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Бүгдийг устгах"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Устгах"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Хайх"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Энэ апп-г суулгаагүй байна"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Энэ дүрсний апп-г суулгаагүй байна. Та үүнийг устгах буюу апп-г хайж суулгах боломжтой."</string>
 </resources>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
new file mode 100644
index 0000000..2e51e7b
--- /dev/null
+++ b/res/values-mr-rIN/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"मुख्‍यपृष्‍ठ"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"अॅप स्थापित केलेला नाही."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"डाउनलोड केलेला अ‍ॅप सुरक्षित मोड मध्‍ये अक्षम केला"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"विजेट"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"विजेट"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem दर्शवा"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
+    <string name="market" msgid="2619650989819296998">"खरेदी करा"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"या मुख्य स्क्रीनवर आयटम ड्रॉप करू शकलो नाही."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"तयार करण्यासाठी विजेट निवडा"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"फोल्डर नाव"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"फोल्डरचे नाव बदला"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ठीक"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"रद्द करा"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"मुख्य स्क्रीनवर जोडा"</string>
+    <string name="group_applications" msgid="3797214114206693605">"अॅप्स"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"विजेट"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"आपल्या मुख्य स्क्रीनवर अधिक जागा नाही."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"या मुख्य स्क्रीनवर आणखी जागा नाही."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"आवडीच्या ट्रे मध्ये आणखी जागा नाही"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"हे विजेट आवडत्या ट्रे साठी खूप मोठे आहे"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट तयार केला."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट काढला."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट आधीपासून अस्तित्वात आहे."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"शॉर्टकट निवडा"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"अॅप निवडा"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"अॅप्स"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"मुख्‍यपृष्‍ठ"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"काढा"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"विस्थापित करा"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"काढा"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"विस्थापित करा"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"अॅप माहिती"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"शोधा"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"व्हॉइस शोध"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"अॅप्स"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"काढा"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अद्यतन विस्थापित करा"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"अॅप विस्थापित करा"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"अॅप तपशील"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 अॅप निवडला"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 विजेट निवडले"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 फोल्डर निवडले"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 शॉर्टकट निवडला"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट स्‍थापित करा"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"शॉर्टकट विस्‍थापित करा"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट काढण्यास अॅप ला अनुमती देते."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट वाचा"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट लिहा"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"विजेट लोड करण्यात समस्या"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"हा सिस्टम अॅप आहे आणि विस्थापित केला जाऊ शकत नाही."</string>
+    <string name="dream_name" msgid="1530253749244328964">"रॉकेट लाँचर"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"अनामित फोल्डर"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"मुख्य स्क्रीन %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$d पैकी %1$d पृष्ठ"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d पैकी %1$d मुख्य स्क्रीन"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d पैकी %1$d Apps पृष्ठ"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d पैकी %1$d विजेट पृष्ठ"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"सुस्वागतम"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"जसे पाहिजे तसे वापरा."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"अॅप्स आणि फोल्डरसाठी आणखी स्क्रीन तयार करा"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"आपली अॅप चिन्हे कॉपी करा"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"आपल्या जुन्या मुख्य स्क्रीनवरून चिन्हे आणि फोल्डर आयात करायची?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"चिन्हे कॉपी करा"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"नव्याने प्रारंभ करा"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"आपले स्थान व्यवस्थापित करा"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, विजेट आणि सेटिंग्ज व्यवस्थापित करण्यासाठी पार्श्वभूमीस स्पर्श करा आणि धरून ठेवा."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"येथे एक फोल्डर आहे"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"यासारखे एखादे तयार करण्यासाठी अॅप ला स्पर्श करा आणि धरून ठेवा, नंतर तो दुसर्‍यावर हलवा."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ठीक"</string>
+    <string name="folder_opened" msgid="94695026776264709">"फोल्डर उघडले, <xliff:g id="WIDTH">%1$d</xliff:g> बाय <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"फोल्डर बंद करण्यासाठी स्पर्श करा"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"नवे नाव जतन करण्यासाठी स्पर्श करा"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"फोल्डर बंद"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"फोल्डरचे नाव बदलून <xliff:g id="NAME">%1$s</xliff:g> असे ठेवले"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"सेटिंग्ज"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षारत"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड करत आहे"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"स्थापित करत आहे"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"पुनर्स्थापित झाले नाही"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"सर्व काढा"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"हा अॅप स्थापित केलेला नाही"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अॅप स्थापित केलेला नाही. आपण ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे स्थापित करू शकता."</string>
+</resources>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index c555c56..3c58762 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Laman Utama"</string>
     <string name="uid_name" msgid="7820867637514617527">"Apl Teras Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Tetapkan kertas dinding"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d dipilih"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d dipilih"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d dipilih"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Kertas dinding %1$d daripada %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Memilih <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Padam"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pilih imej"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Kertas dinding"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Pangkas kertas dinding"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Apl yang dimuat turun dilumpuhkan dalam mod Selamat"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Papar Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Tiada lagi ruang pada skrin Laman Utama anda."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Tiada lagi ruang pada skrin Laman Utama ini."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Tiada lagi ruang pada kerusi panas."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Widget ini terlalu besar untuk kerusi panas."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Tiada ruang dalam dulang Kegemaran lagi"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget ini terlalu besar untuk dulang Kegemaran"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dibuat."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dialih keluar."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah wujud."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"tulis tetapan dan pintasan Laman Utama"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Membenarkan apl menukar tetapan dan pintasan di Laman Utama."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Masalah memuatkan widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Persediaan"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini ialah apl sistem dan tidak boleh dinyahpasang."</string>
     <string name="dream_name" msgid="1530253749244328964">"Pelancar Roket"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
@@ -102,13 +92,14 @@
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Buat lebih banyak skrin untuk apl dan folder"</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"Salin ikon apl anda"</string>
-    <string name="migration_cling_description" msgid="2752413805582227644">"Import ikon dan folder dari skrin Laman Utama anda?"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Import ikon dan folder dari skrin Laman Utama lama anda?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"SALIN IKON"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"MULAKAN YANG BAHARU"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Susun ruang anda"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Sentuh &amp; tahan latar belakang untuk mengurus kertas dinding, widget dan tetapan."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Pilih beberapa apl"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Untuk menambahkan apl pada skrin Laman Utama anda, sentuh &amp; tahan apl."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Kertas dinding, widget &amp; tetapan"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Sentuh &amp; tahan latar belakang untuk memperibadikan"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"FAHAM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ini ada folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Untuk membuat satu folder seperti ini, sentuh &amp; tahan apl, kemudian alihkan ke atas folder lain."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folder ditutup"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Folder dinamakan semula kepada <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Kertas dinding"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Tetapan"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Menunggu"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Memuat turun"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Memasang"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Tidak diketahui"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Tak dipulihkan"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Buang Semua"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Alih keluar"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Carian"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Apl ini tidak dipasang"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Apl untuk ikon ini tidak dipasang. Anda boleh mengalih keluar atau mencari dan memasang apl itu secara manual."</string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index d2f6bb1..f50a5db 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -41,7 +41,6 @@
     <string name="group_applications" msgid="2103752818818161976">"Aplikasi"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
     <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
-    <string name="group_wallpapers" msgid="1568191644272224858">"Kertas dinding"</string>
     <string name="completely_out_of_space" msgid="1759078539443491182">"Tiada lagi ruang pada skrin Utama anda."</string>
     <string name="out_of_space" msgid="8365249326091984698">"Tiada lagi ruang pada skrin Utama ini"</string>
     <string name="hotseat_out_of_space" msgid="6304886797358479361">"Tiada lagi ruang pada kerusi panas."</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
new file mode 100644
index 0000000..8048b02
--- /dev/null
+++ b/res/values-my-rMM/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher၃"</string>
+    <string name="home" msgid="7658288663002113681">"ပင်မစာမျက်နှာ"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Androidပင်မ အပ်ပလီကေးရှင်းများ"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"အပ်ပလီကေးရှင်း မထည့်သွင်းထားပါ"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ဒေါင်းလုဒ် appကို လုံခြုံရေး မုဒ်ထဲမှာ ပိတ်ထား"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"ဝဒ်ဂျက်များ"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"ဝဒ်ဂျက်များ"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem ကိုပြရန်"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"ဝဒ်ဂျက်တစ်ခုကို ကောက်ယူရန် ဖိနှိပ်ထားပါ"</string>
+    <string name="market" msgid="2619650989819296998">"စျေးဝယ်ရန်"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"ပင်မမျက်နှာစာတွင် အရာများ ချ လို့ မရတော့ပါ"</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ဝဒ်ဂျက်တစ်ခုအား ပြုဖန်တီးရန် ရွေးပါ"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"အကန့်အမည်"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"အကန့်အမည်ပြောင်းရန်"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ကောင်းပြီ"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"ပယ်ဖျက်သည်"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</string>
+    <string name="group_applications" msgid="3797214114206693605">"အပ်ပလီကေးရှင်းများ"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"အတိုကောက်မှတ်သားမှုများ"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"ဝဒ်ဂျက်များ"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"ပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"အနှစ်သက်ဆုံးများ ထားရာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ဤဝဒ်ဂျက်မှာ အနှစ်သက်ဆုံးအရာများထားရာနေရာ အတွက် ကြီးလွန်းနေပါသည်"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ကို ပြုလုပ်ပြီးပါပြီ"</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ကို ဖယ်ရှားပြီးပါပြီ"</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ရှိပြီးသား ဖြစ်နေပါသည်"</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"အတိုကောက်မှတ်သားမှုကို ရွေးရန်"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"အပလီကေးရှင်း တစ်ခုခုကို ရွေးချယ်ပါ"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"အပ်ပလီကေးရှင်းများ"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"ပင်မစာမျက်နှာ"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ဖယ်ရှာခြင်း"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ဖယ်ရှားခြင်း"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"ဖယ်ရှာခြင်း"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ဖယ်ရှားခြင်း"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"အပ်ပလီကေးရှင်း အချက်အလက်များ"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"ရှာဖွေခြင်း"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"အသံဖြင့် ရှာဖွေခြင်း"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"အပ်ပလီကေးရှင်းများ"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"ဖယ်ရှာခြင်း"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"အဆင့်မြှင့်ခြင်းကို ဖယ်ရှားပါ"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"အပ်ပလီကေးရှင်းကို ဖယ်ရှားပါ"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"အပ်ပလီကေးရှင်း အသေးစိတ် အချက်အလက်"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"အပ်ပလီကေးရှင်းတစ်ခု ရွေးချယ်ထားပြီး"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"ဝဒ်ဂျက်တစ်ခု ရွေးချယ်ထားပြီး"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"အကန့် တစ်ခု ရွေးချယ်ထားပြီး"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"အတိုကောက်မှတ်သားမှုတစ်ခု ရွေးချယ်ထားပြီး"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"အတိုကောက်မှတ်သားမှုများအား ထည့်သွင်းခြင်း"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"အသုံးပြုသူ လုပ်ဆောင်မှုမရှိပဲ အပ်ပလီကေးရှင်းကို အတိုကောက်မှတ်သားမှုများ ပြုလုပ်ခွင့် ပေးခြင်း"</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"အတိုကောက်မှတ်သားမှုများ ဖယ်ထုတ်ခြင်း"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"အပ်ပလီကေးရှင်းအား အသုံးပြုသူ မပါဝင်ပဲ အတိုကောက်မှတ်သားမှုများ ဖယ်ရှားခွင့် ပြုခြင်း"</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ဖတ်ခြင်း"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"ပင်မမျက်နှာစာတွင်ရှိသော အပြင်အဆင်နှင့် အတိုကောက်မှတ်သားမှုများကို အပ်ပလီကေးရှင်းအား ဖတ်ခွင့်ပြုခြင်း"</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ရေးသားခြင်း"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"ပင်မမျက်နှာစာတွင် ရှိသော အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများ ကို အပ်ပလီကေးရှင်းအား ပြောင်းခွင့်ပြုခြင်း"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"ဝဒ်ဂျက် တင်ရာတွင် ပြသနာ ရှိပါသည်"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"ဤအပ်ပလီကေးရှင်းမှာ စစ်စတန်ပိုင်းဆိုင်ရာ အပ်ပလီကေးရှင်းဖြစ်ပါသည်။ ထုတ်ပစ်၍ မရပါ"</string>
+    <string name="dream_name" msgid="1530253749244328964">"ဒုံပျံ ပစ်လွှတ်သောအရာ"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"အမည်မရှိအကန့်"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"ပင်မစာမျက်နှာ %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"စာမျက်နှာ %1$d မှ %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"ပင်မစာမျက်နှာ %1$d မှ %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"အပ်ပလီကေးရှင်းပြ စာမျက်နှာ %1$d မှ %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ဝဒ်ဂျက်ပြ စာမျက်နှာ %1$d မှ %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"ကြိုဆိုပါသည်"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"ကိုယ့်အိမ်ကိုယ့်ယာလို သဘောထားပါ"</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"အပ်ပလီကေးရှင်း နှင့် အကန့်များအတွက် ဖန်သားပြင်မှာ ထပ်ထည့်ပါ"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"အပ်ပလီကေးရှင်းပုံညွှန်းများကို ကူးယူပါ"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"ပင်မစာမျက်နှာအဟောင်းမှ ပုံညွှန်းများ နှင့် အကန့်များကို ယူလာပါမလား"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"START FRESH"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"စနစ်တကျဖြစ်အောင် ပြုလုပ်ပါ"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"နောက်ခံကို ဖိကိုင်၍ နောက်ခံပုံ၊ဝဒ်ဂျက်များ၊အပြင်အဆင်များကို ထိန်းချုပ်ပါ"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"ဒီမှာ အကန့်တစ်ခုဖြစ်ပါသည်"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ဤကဲ့သို့လုပ်ရန်အတွက်၊ အပ်ပလီကေးရှင်းတစ်ခုကို ဖိကိုင်ပြီး နောက်တစ်ခုပေါ်သို့ ရွှေ့လိုက်ပါ"</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ကောင်းပြီ"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ဖွင့်ထားသောအကန့်, <xliff:g id="WIDTH">%1$d</xliff:g> နှင့် <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"အကန့်ကို ပိတ်ရန် ဖိကိုင်ပါ"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"အမည်ပြောင်းခြင်း အတည်ပြုရန် ဖိကိုင်ပါ"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ပိတ်ထားသောအကန့်"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"ပြောင်းလဲလိုက်သော အကန့်အမည် <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"အကန့်အမည်: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"ဝဒ်ဂျက်များ"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"နောက်ခံများ"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"အပြင်အဆင်များ"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"စောင့်နေ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ဒေါင်းလုဒ် လုပ်နေ"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"တပ်ဆင်နေ"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"မသိရ"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ပြန်မဖေါ်ခဲ့"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"အားလုံး ဖယ်ရှားရန်"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ဖယ်ရှားရန်"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ရှာဖွေရန်"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"App မတပ်ဆင်ရသေးပါ"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ဤအိုင်ကွန်အတွက် app အားမထည့်သွင်းထားပါ။ You can remove it, or search for the app and install it manually."</string>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 9bc9e69..ff8280e 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Startside"</string>
     <string name="uid_name" msgid="7820867637514617527">"Kjerneapper for Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Angi bakgrunn"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d valgt"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d valgt"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d valgt"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Bakgrunn %1$d of %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Valgt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Slett"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Velg bilde"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Bakgrunner"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Beskjær bakgrunnen"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installert."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"En nedlastet app er deaktivert i sikker modus"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Moduler"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Moduler"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis minne"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Moduler"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Ikke mer plass på startsidene dine."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Denne startsiden er full."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Dokksonen er full."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Denne modulen er for stor for dokksonen."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritter-skuffen er full"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denne modulen er for stor for Favoritter-skuffen."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» er opprettet."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» er fjernet."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» fins allerede."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"angi startsideinnstillinger og -snarveier"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Lar appen endre innstillingene og snarveiene på startsiden."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem ved innlasting av modul"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Konfigurering"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp som ikke kan avinstalleres."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Mappe uten navn"</string>
@@ -102,13 +92,14 @@
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Opprett flere sider for apper og mapper"</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"Kopiér appikonene dine"</string>
-    <string name="migration_cling_description" msgid="2752413805582227644">"Vil du importere ikoner og mapper fra de gamle startsidene?"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Vil du importere ikoner og mapper fra dine gamle startsider?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIÉR IKONENE"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"START PÅ NYTT"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser plassen din"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Trykk og hold på bakgrunnen for å administrere bakgrunnen, moduler og innstillinger."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Velg noen apper"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Trykk og hold på en app for å legge den til på startsiden."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Bakgrunner, moduler og innstillinger"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Trykk og hold på bakgrunnen for å tilpasse den"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SKJØNNER"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Dette er en mappe"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"For å opprette en som denne, trykker og holder du på en app og flytter den over en annen."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mappen ble lukket"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mappen heter nå <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Moduler"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunner"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Innstillinger"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Venter …"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Laster ned …"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installerer …"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Ukjent"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ikke gjenoppr."</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Fjern alle"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Søk"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Denne appen er ikke installert"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen for dette ikonet er ikke installert. Du kan fjerne det, eller prøve å søke etter appen og installere den manuelt."</string>
 </resources>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000..fe75ea7
--- /dev/null
+++ b/res/values-ne-rNP/strings.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"गृह"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android मूल अनुप्रयोगहरू"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"अनुप्रयोग स्थापित छैन।"</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"विजेटहरू"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"विजेटहरू"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem देखाउनुहोस्"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"एउटा विजेटलाई टिप्नको लागि टच गरेर होल्ड गर्नुहोस्।"</string>
+    <string name="market" msgid="2619650989819296998">"पसल"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"यो गृह स्क्रिनमा वस्तु खसाउन सकिँदैन।"</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"सृजना गर्नको लागि विजेट छान्नुहोस्"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"फोल्डरको नाम"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"फोल्डरलाई पुनःनामाकरण गर्नुहोस्"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ठिक छ"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"रद्द गर्नुहोस्"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"गृह स्क्रिनमा थप्नुहोस्"</string>
+    <string name="group_applications" msgid="3797214114206693605">"अनुप्रयोगहरू"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"सर्टकटहरू"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"विजेटहरू"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"यो गृह स्क्रिनहरूमा कुनै थप ठाउँ छैन"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"यो गृह स्क्रिनमा कुनै थप ठाउँ छैन।"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"मनपर्ने ट्रे अब कुनै ठाँउ छैन"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"यो विजेट मनपर्ने ट्रे को लागि निकै ठूलो छ"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" सिर्जित गरियो।"</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" हटाइयो।"</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" पहिल्यै अवस्थित छ।"</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"सर्टकट छान्नुहोस्"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"अनुप्रयोग छनौट गर्नुहोस्"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"अनुप्रयोगहरू"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"गृह"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"हटाउनुहोस्"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"हटाउनुहोस्"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"हटाउनुहोस्"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"हटाउनुहोस्"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"अनुप्रयोग जानकारी"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"खोज्नुहोस्"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"ध्वनि खोज"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"अनुप्रयोगहरू"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"हटाउनुहोस्"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अद्यावधिक अस्थापित गर्नुहोस्"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"अनुप्रयोग अस्थापना गर्नुहोस्"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"अनुप्रयोग विवरणहरु"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"१ अनुप्रयोग चयन गरियो"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"१ विजेट चयन गरियो"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"१ फोल्डर चयन गरियो"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"१ सर्टकट चयन गरियो"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"सर्टकट स्थापना गर्नेहोस्"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"सर्टकटहरूको स्थापन रद्द गर्नुहोस्"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"अनुप्रयोगलाई उपयोगकर्ताको हस्तक्षेप बिना सर्टकटहरूलाई हटाउन अनुमति दिनुहोस्।"</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"गृह सेटिङहरू र सर्टकटहरू पढ्नुहोस्"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"गृहमा एउटा अनुप्रयोगलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।"</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"गृह सेटिङहरू र सर्टकटहरू लेख्नुहोस्"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"गृहमा एउटा अनुप्रयोगलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"समस्या लोडिङ गर्ने विजेट"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"यो प्रणाली अनुप्रयोग हो र यसलाई स्थापना रद्द गर्न सकिँदैन।"</string>
+    <string name="dream_name" msgid="1530253749244328964">"रकेट लन्चर"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"बेनाम फोल्डर"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"गृह स्क्रिन %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d को %1$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"गृह स्क्रिन %2$d को %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"अनुप्रयोग पृष्ठ %2$d को %1$d"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for apps_customize_widgets_scroll_format (3106209519974971521) -->
+    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"स्वागतम"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"गृह आरामसँग बस्नुहोस्"</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"अनुप्रयोगहरु र फोल्डरहरुलाई थप स्क्रीनहरु सिर्जना गर्नुहोस्"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"तपाईँको अनुप्रयोग आईकनको प्रतिलिप गर्नुहोस्"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"आफ्नो पुरानो गृह स्क्रीनबाट अाईकन र फोल्डरहरू आयात गर्नुहोस्?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ICONS प्रतिलिप गर्नुहोस्"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"START FRESH"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"आफ्नो ठाउँ व्यवस्थापन गर्नुहोस्"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"वालपेपर, विजेट र सेटिङ्स प्रबन्ध गर्न पृष्ठभूमिलाई टच गरेर होल्ड गर्नुहोस्।"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"यहाँ एउटा फोल्डर छ"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"यस्तै एक किसिमका सिर्जना गर्न, अनुप्रयोगलाई टच गरेर होल्ड गर्नुहोस्, त्यसपछि यसलाई अर्को माथि सार्नुहोस्।"</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ठिक छ"</string>
+    <string name="folder_opened" msgid="94695026776264709">"फोल्डर खुल्यो <xliff:g id="WIDTH">%1$d</xliff:g> बाट <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"फोल्डर बन्द गर्नको लागि टच गर्नुहोस्"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"पुन: नामाकरण बचत गर्न टच गर्नुहोस्।"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"फोल्डर बन्द भयो"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"फोल्डर <xliff:g id="NAME">%1$s</xliff:g> मा पुनःनामाकरण गरियो।"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"विजेटहरू"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"वालपेपरहरु"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"सेटिंङहरू"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"पर्खँदै"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड हुँदै"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"स्थापना गर्दै"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"पुनर्स्थापित भएन"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"सबै हटाउनुहोस्"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"खोजी गर्नुहोस्"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"यो अनुप्रयोग स्थापित छैन"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"यो प्रतिमाका लागि अनुप्रयोगलाई स्थापना गरिएको छैन। तपाईँ यसलाई हटाउन, वा अनुप्रयोग खोजी र स्वयं यो स्थापित गर्न सक्नुहुन्छ।"</string>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index e5df49c..470eb87 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Startpagina"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android-kernapps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Achtergrond instellen"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d geselecteerd"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d geselecteerd"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d geselecteerd"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Achtergrond %1$d van %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> is geselecteerd"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Verwijderen"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Afbeelding kiezen"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Achtergronden"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Achtergrond bijsnijden"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"App is niet geïnstalleerd."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Gedownloade app uitgeschakeld in veilige modus"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Geheugen weergeven"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Er is geen ruimte meer op uw startschermen."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Er is geen ruimte meer op dit startscherm."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Er is geen ruimte meer op de hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Deze widget is te groot voor de hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen ruimte meer in het vak \'Favorieten\'"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Deze widget is te groot voor het vak \'Favorieten\'"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is gemaakt."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is verwijderd."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' bestaat al."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"instellingen en snelkoppelingen op de startpagina schrijven"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"De app toestaan de instellingen en snelkoppelingen op de startpagina te wijzigen."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Probleem bij het laden van widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuratie"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is een systeemapp die niet kan worden verwijderd."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Naamloze map"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"OPNIEUW BEGINNEN"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Uw ruimte indelen"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Blijf de achtergrond aanraken om de achtergrond, widgets en instellingen te beheren."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Selecteer een aantal apps"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Als u een app wilt toevoegen aan het startscherm, blijft u de app aanraken."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Achtergronden, widgets en instellingen"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Blijf de achtergrond aanraken om deze aan te passen"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Dit is een map"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Als u een map zoals deze wilt maken, blijft u een app aanraken en schuift u deze boven op een andere app."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Map gesloten"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"De naam van de map is gewijzigd in <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergronden"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Instellingen"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Wachten"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Downloaden"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installeren"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Niet hersteld"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Alles verwijderen"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Zoeken"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Deze app is niet geïnstalleerd"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"De app voor dit pictogram is niet geïnstalleerd. U kunt het pictogram verwijderen of de app zoeken en handmatig installeren."</string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 964e8a1..61a51e0 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Ekran główny"</string>
     <string name="uid_name" msgid="7820867637514617527">"Główne aplikacje Androida"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Ustaw tapetę"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Wybrane: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Wybrane: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Wybrane: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Tapeta %1$d z %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Wybrano <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Usuń"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Wybierz obraz"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Tapety"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Przytnij tapetę"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikacja nie jest zainstalowana."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Pobrana aplikacja została wyłączona w trybie awaryjnym"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widżety"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widżety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaż pamięć"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widżety"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Brak miejsca na ekranach głównych."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Brak miejsca na tym ekranie głównym."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Brak miejsca w kieszonce."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ten widżet jest za duży, by umieścić go w kieszonce."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Brak miejsca w Ulubionych"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ten widżet jest za duży, by zmieścił się w Ulubionych"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został utworzony."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został usunięty."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Skrót „<xliff:g id="NAME">%s</xliff:g>” już istnieje."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"zapisywanie ustawień i skrótów na ekranie głównym"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Umożliwia aplikacji zmianę ustawień i skrótów na ekranie głównym."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problem podczas ładowania widżetu"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Konfiguracja"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"To aplikacja systemowa i nie można jej odinstalować."</string>
     <string name="dream_name" msgid="1530253749244328964">"Wyrzutnia rakiet"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Folder bez nazwy"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ZACZNIJ OD NOWA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Uporządkuj obszar roboczy"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Kliknij i przytrzymaj tło, by zmienić tapetę, widżety lub ustawienia."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Wybierz kilka aplikacji"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Aby dodać aplikację na ekran główny, dotknij i przytrzymaj jej ikonę."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Tapety, widżety i ustawienia"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Kliknij i przytrzymaj tło, by dostosować"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Tu jest folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Aby utworzyć taki sam, kliknij i przytrzymaj aplikację, a następnie przenieś ją na następną."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folder zamknięty"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Nazwa folderu zmieniona na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widżety"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Ustawienia"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Oczekiwanie"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Pobieranie"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalowanie"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Brak informacji"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nie przywrócono"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Usuń wszystkie"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Usuń"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Szukaj"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacja nie jest zainstalowana"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacja, której odpowiada ta ikona, nie jest zainstalowana. Możesz usunąć ikonę lub wyszukać aplikację i zainstalować ją ręcznie."</string>
 </resources>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 7753ab3..c20f57b 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -16,9 +16,6 @@
 
 <resources>
 <!-- AppsCustomize -->
-    <integer name="apps_customize_cling_focused_x">1</integer>
-    <integer name="apps_customize_cling_focused_y">1</integer>
-
     <integer name="apps_customize_widget_cell_count_x">2</integer>
     <integer name="apps_customize_widget_cell_count_y">3</integer>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 6ef84b0..2fe062a 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Ecrã principal"</string>
     <string name="uid_name" msgid="7820867637514617527">"Aplicações principais do Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Definir imagem fundo"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selecionado(s)"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selecionado(s)"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selecionado(s)"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Imagem de fundo %1$d de %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> selecionado"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Eliminar"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Escolher imagem"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Imagens de fundo"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Recortar imagem de fundo"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicação transferida desativada no Modo de segurança"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Sem espaço suficiente nos Ecrãs principais."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Sem espaço suficiente neste Ecrã principal."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Sem espaço suficiente na barra personalizável."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Este widget é demasiado grande para a barra personalizável."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Não existe mais espaço no tabuleiro de Favoritos"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget é demasiado grande para o tabuleiro de Favoritos"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Atalho “<xliff:g id="NAME">%s</xliff:g>” criado."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"O atalho “<xliff:g id="NAME">%s</xliff:g>” foi removido."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"O atalho “<xliff:g id="NAME">%s</xliff:g>” já existe."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"escrever definições e atalhos do Ecrã principal"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite à aplicação alterar as definições e os atalhos no Ecrã Principal."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema ao carregar o widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuração"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"É uma aplicação de sistema e não pode ser desinstalada."</string>
     <string name="dream_name" msgid="1530253749244328964">"Lança-mísseis"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"COMEÇAR DO INÍCIO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizar o seu espaço"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Toque sem soltar no fundo para gerir a imagem de fundo, os widgets e as definições."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Escolher algumas aplicações"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Para adicionar uma aplicação ao Ecrã principal, toque na mesma sem soltar."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Imagens de fundo, widgets e definições"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Toque sem soltar no fundo para personalizar"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"COMPREENDI"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Eis uma pasta"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para criar uma pasta, toque sem soltar numa aplicação e arraste-a para cima de outra aplicação."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Pasta fechada"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Nome de pasta alterado para <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Imagens de fundo"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Definições"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"A aguardar"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"A transferir "</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"A instalar"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Não restaurado"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Remover todos"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicação não está instalada"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"A aplicação deste ícone não está instalada. Pode removê-lo ou pesquisar a aplicação e instalá-la manualmente."</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index d2ff1b4..ddbb253 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -21,21 +21,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"Início"</string>
-    <string name="uid_name" msgid="7820867637514617527">"Principais aplicativos do Android"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Principais apps do Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Definir plano de fundo"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selecionados"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selecionados"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selecionados"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Plano de fundo %1$d de %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> selecionado"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Excluir"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Escolher imagem"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Planos de fundo"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Cortar plano de fundo"</string>
-    <string name="activity_not_found" msgid="8071924732094499514">"O aplicativo não está instalado."</string>
+    <string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"App transferido por download desativado no modo de segurança"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memória"</string>
@@ -49,68 +38,70 @@
     <string name="rename_action" msgid="5559600076028658757">"Ok"</string>
     <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
     <string name="menu_item_add_item" msgid="1264911265836810421">"Adicionar à tela inicial"</string>
-    <string name="group_applications" msgid="3797214114206693605">"Aplicativos"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"Atalhos"</string>
     <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Não há mais espaço nas telas iniciais."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Não há mais espaço na tela inicial."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Não há mais espaço no hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Este widget é muito grande para o hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Sem espaço na bandeja de favoritos"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"O widget é muito grande para a bandeja de favoritos"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Atalho \"<xliff:g id="NAME">%s</xliff:g>\" criado."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
     <string name="title_select_shortcut" msgid="6680642571148153868">"Selecione um atalho"</string>
-    <string name="title_select_application" msgid="3280812711670683644">"Selecione um aplicativo"</string>
-    <string name="all_apps_button_label" msgid="9110807029020582876">"Aplicativos"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Selecione um app"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Início"</string>
     <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remover"</string>
     <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
     <string name="delete_target_label" msgid="1822697352535677073">"Remover"</string>
     <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
-    <string name="info_target_label" msgid="8053346143994679532">"Informações do aplicativo"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Informações do app"</string>
     <string name="accessibility_search_button" msgid="1628520399424565142">"Pesquisar"</string>
     <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Pesquisa por voz"</string>
-    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicativos"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
     <string name="accessibility_delete_button" msgid="6466114477993744621">"Remover"</string>
     <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar atualização"</string>
-    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar aplicativo"</string>
-    <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalhes do aplicativo"</string>
-    <string name="cab_app_selection_text" msgid="374688303047985416">"Um aplicativo selecionado"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar app"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalhes do app"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"Um app selecionado"</string>
     <string name="cab_widget_selection_text" msgid="1833458597831541241">"Um widget selecionado"</string>
     <string name="cab_folder_selection_text" msgid="7999992513806132118">"Uma pasta selecionada"</string>
     <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Um atalho selecionado"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
-    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que um aplicativo adicione atalhos sem intervenção do usuário."</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que um app adicione atalhos sem intervenção do usuário."</string>
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar atalhos"</string>
-    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite que o aplicativo remova atalhos sem a intervenção do usuário."</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite que o app remova atalhos sem a intervenção do usuário."</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"ler configurações e atalhos da tela inicial"</string>
-    <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que o aplicativo leia as configurações e os atalhos na tela inicial."</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que o app leia as configurações e os atalhos na tela inicial."</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"gravar configurações e atalhos da tela inicial"</string>
-    <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que o aplicativo altere as configurações e os atalhos na tela inicial."</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que o app altere as configurações e os atalhos na tela inicial."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema ao carregar o widget"</string>
-    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Este é um aplicativo do sistema e não pode ser desinstalado."</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configuração"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Este é um app do sistema e não pode ser desinstalado."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
     <string name="workspace_description_format" msgid="2950174241104043327">"Tela inicial %1$d"</string>
     <string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Tela inicial %1$d de %2$d"</string>
-    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicativos, %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de apps, %1$d de %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets, %1$d de %2$d"</string>
     <string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Fique à vontade."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
-    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crie mais telas para aplicativos e pastas"</string>
-    <string name="migration_cling_title" msgid="9181776667882933767">"Copiar ícones de aplicativos"</string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crie mais telas para apps e pastas"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copiar ícones de apps"</string>
     <string name="migration_cling_description" msgid="2752413805582227644">"Importar ícones e pastas de suas telas iniciais antigas?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONES"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"COMEÇAR DO ZERO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organize seu espaço"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Toque e mantenha pressionada a tela de fundo para gerenciar o plano de fundo, os widgets e as configurações."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Escolha alguns aplicativos"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Para adicionar um aplicativo a sua tela inicial, toque e mantenha-o pressionado."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Plano de fundo, widgets e configurações"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Toque e mantenha pressionado o segundo plano para personalizar"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDI"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Aqui está uma pasta"</string>
-    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para criar uma pasta como esta, mantenha pressionado um aplicativo e mova-o para cima de outro."</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para criar uma pasta como esta, mantenha pressionado um app e mova-o para cima de outro."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Ok"</string>
     <string name="folder_opened" msgid="94695026776264709">"Pasta aberta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"Toque para fechar a pasta"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Pasta fechada"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Pasta renomeada para <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Planos de fundo"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Configurações"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Aguardando"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Transferindo"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Não restaurado"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Remover tudo"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Este app não está instalado"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"O app deste ícone não está instalado. Você pode remover o ícone, ou procurar o app e instalá-lo manualmente."</string>
 </resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index b1ef2ec..be35c6b 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -26,23 +26,6 @@
     <!-- no translation found for uid_name (7820867637514617527) -->
     <skip />
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <!-- no translation found for wallpaper_instructions (563973358787555519) -->
-    <skip />
-    <!-- no translation found for number_of_items_selected:zero (7464587177007785408) -->
-    <!-- no translation found for number_of_items_selected:one (142482526010824029) -->
-    <!-- no translation found for number_of_items_selected:other (1418352074806573570) -->
-    <!-- no translation found for wallpaper_accessibility_name (1655953108132967972) -->
-    <skip />
-    <!-- no translation found for announce_selection (8338254712932127413) -->
-    <skip />
-    <!-- no translation found for wallpaper_delete (8095005658756613921) -->
-    <skip />
-    <!-- no translation found for pick_image (1272073934062909527) -->
-    <skip />
-    <!-- no translation found for pick_wallpaper (8179698221502010609) -->
-    <skip />
-    <!-- no translation found for crop_wallpaper (8334345984491368009) -->
-    <skip />
     <!-- no translation found for activity_not_found (8071924732094499514) -->
     <skip />
     <!-- no translation found for widgets_tab_label (2921133187116603919) -->
@@ -81,9 +64,9 @@
     <skip />
     <!-- no translation found for out_of_space (4691004494942118364) -->
     <skip />
-    <!-- no translation found for hotseat_out_of_space (9139760413395605841) -->
+    <!-- no translation found for hotseat_out_of_space (7448809638125333693) -->
     <skip />
-    <!-- no translation found for invalid_hotseat_item (1211534262129849507) -->
+    <!-- no translation found for invalid_hotseat_item (5779907847267573691) -->
     <skip />
     <!-- no translation found for shortcut_installed (1701742129426969556) -->
     <skip />
@@ -185,10 +168,6 @@
     <skip />
     <!-- no translation found for workspace_cling_move_item (528201129978005352) -->
     <skip />
-    <!-- no translation found for all_apps_cling_title (34929250753095858) -->
-    <skip />
-    <!-- no translation found for all_apps_cling_add_item (400866858451850784) -->
-    <skip />
     <!-- no translation found for folder_cling_title (3894908818693254164) -->
     <skip />
     <!-- no translation found for folder_cling_create_folder (6158215559475836131) -->
@@ -207,14 +186,20 @@
     <skip />
     <!-- no translation found for folder_name_format (6629239338071103179) -->
     <skip />
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <!-- no translation found for widget_button_text (2880537293434387943) -->
     <skip />
     <!-- no translation found for wallpaper_button_text (8404103075899945851) -->
     <skip />
     <!-- no translation found for settings_button_text (8119458837558863227) -->
     <skip />
+    <!-- no translation found for package_state_enqueued (6227252464303085641) -->
+    <skip />
+    <!-- no translation found for package_state_downloading (4088770468458724721) -->
+    <skip />
+    <!-- no translation found for package_state_installing (7588193972189849870) -->
+    <skip />
+    <!-- no translation found for package_state_unknown (7592128424511031410) -->
+    <skip />
+    <!-- no translation found for package_state_error (7672093962724223588) -->
+    <skip />
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 277b1df..04aebc8 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Ecran de pornire"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Setați imaginea de fundal"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d selectate"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d selectat"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d selectate"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Imaginea de fundal %1$d din %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"S-a selectat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Ștergeți"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Alegeți imaginea"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Imagini de fundal"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Decupați imaginea de fundal"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicația descărcată este dezactivată în modul de siguranță"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgeturi"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgeturi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afișați memoria"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgeturi"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Nu mai este loc pe ecranele de pornire."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Nu mai este loc pe acest Ecran de pornire."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Nu mai este loc în bara de lansare rapidă."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Acest widget este prea mare pentru bara de lansare rapidă."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Spațiu epuizat în bara Preferate"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Acest widget este prea mare pentru bara Preferate"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>\" a fost creată."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” a fost eliminată."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” există deja."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"scrie setări și comenzi rapide pentru ecranul de pornire"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite aplicației să modifice setările și comenzile rapide din ecranul de pornire."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problemă la încărcarea widgetului"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Configurați"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Aceasta este o aplicație de sistem și nu poate fi dezinstalată."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Dosar fără nume"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"REÎNCEPEȚI"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizați-vă spațiul"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Atingeți lung fundalul pentru a gestiona imaginea de fundal, widgeturile și setările."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Alegeți unele aplicații"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Atingeți lung o aplicație pentru a o adăuga pe ecranul de pornire."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Imagini de fundal, widgeturi și setări"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Atingeți lung fundalul pentru a-l personaliza"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"AM ÎNȚELES"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Iată un dosar"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pentru a crea un dosar similar, atingeți și țineți degetul pe o aplicație, apoi mutați-o deasupra alteia."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Dosar închis"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Dosar redenumit <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgeturi"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Imagini de fundal"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Setări"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"În așteptare"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Se descarcă"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Se instalează"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Necunoscut"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nerestabilit"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminați-le pe toate"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminați"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Căutați"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Aplicația nu este instalată"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplicația pentru această pictogramă nu este instalată. Puteți să ștergeți pictograma sau să căutați aplicația și s-o instalați manual."</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index f8343cc..b1d7713 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Главный экран"</string>
     <string name="uid_name" msgid="7820867637514617527">"Основные приложения Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Установить как обои"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Выбрано: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Выбрано: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Выбрано: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Обои %1$d из %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Выбран элемент \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Удалить"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Выбрать изображение"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Обои"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Обрезать обои"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Приложение удалено"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Скачанное приложение отключено в безопасном режиме"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Виджеты"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Виджеты"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"На главных экранах все занято"</string>
     <string name="out_of_space" msgid="4691004494942118364">"На этом экране все занято"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Нет свободного места в слоте"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Виджет слишком велик для слота"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"В разделе \"Избранное\" больше нет места"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Виджет слишком велик для раздела \"Избранное\""</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" создан"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" удален"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" уже существует"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"Изменение настроек и ярлыков главного экрана"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Приложение сможет изменять настройки и ярлыки на главном экране."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Не удалось загрузить виджет"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Настройка"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Это системное приложение, его нельзя удалить."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Папка без названия"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Главные экран %1$d из %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Приложения: стр. %1$d из %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Виджеты: стр. %1$d из %2$d"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Добро пожаловать!"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Будьте как дома"</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Создание дополнительных экранов для приложений и папок"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"Копировать значки приложений"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Импортировать значки и папки со старого главного экрана?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРОВАТЬ ЗНАЧКИ"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"ИСПОЛЬЗОВАТЬ СТАНДАРТНЫЙ МАКЕТ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Организация рабочего пространства"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Чтобы перейти к управлению обоями, виджетами и настройками, нажмите на фоновое изображение и удерживайте его."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Выберите приложения"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Чтобы добавить приложение на главный экран, нажмите на значок и удерживайте его."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Обои, виджеты и настройки"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Чтобы выполнить настройку, коснитесь фона и удерживайте его"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ОК"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Это папка"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Чтобы создать папку, нажмите и удерживайте значок приложения, а затем перетащите его на другой значок."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"ОК"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Папка закрыта"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Папка переименована в \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Виджеты"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Обои"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Настройки"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Ожидается"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Скачивается"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Устанавливается"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Неизвестно"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Не восстановлен"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Удалить все"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Удалить"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Найти"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Приложение не установлено"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Приложение не установлено. Вы можете удалить значок или найти приложение и установить его вручную."</string>
 </resources>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
new file mode 100644
index 0000000..d334da9
--- /dev/null
+++ b/res/values-si-rLK/strings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"මුල් පිටුව"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android මධ්‍ය යෙදුම්"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"යෙදුම ස්ථාපනය කර නැත."</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"විජට්"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"විජට්"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem පෙන්වන්න"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"විජට් එක ස්පර්ශ කර අහුලා ගැනීමට අල්ලාගෙන සිටින්න."</string>
+    <string name="market" msgid="2619650989819296998">"සාප්පුයාම"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"මෙම මුල් පිටු තිරය වෙත අයිතමය ඇද හෙළිය නොහැකි විය."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"සැදීමට විජට් එක තෝරන්න"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"ෆෝල්ඩරයේ නම"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"ෆෝල්ඩරය නැවත නම් කරන්න"</string>
+    <string name="rename_action" msgid="5559600076028658757">"හරි"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"අවලංගු කරන්න"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"මුල් පිටු තිරය වෙත එක් කරන්න"</string>
+    <string name="group_applications" msgid="3797214114206693605">"යෙදුම්"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"කෙටිමං"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"විජට්"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"මෙම මුල් පිටු තිර මත තවත් ඉඩ නැත."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"මෙම මුල් පිටු තිරය මත තවත් අවසර නැත."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"ප්‍රියතම දෑ ඇති තැටියේ තවත් ඉඩ නොමැත"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ප්‍රියතම දෑ ඇති තැටිය සඳහා මෙම විජටය ඉතා විශාලය"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග සාදන ලදි."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග ඉවත් කෙරිණි."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග දැනටමත් පවතී."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"කෙටිමග තේරීම"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"යෙදුම තේරීම"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"යෙදුම්"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"මුල් පිටුව"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ඉවත් කරන්න"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"අස්ථාපනය කරන්න"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"ඉවත් කරන්න"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"අස්ථාපනය කරන්න"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"යෙදුම් තොරතුරු"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"සොයන්න"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"හඬ සෙවීම"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"යෙදුම්"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"ඉවත් කරන්න"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"යාවත්කාලිනය අස්ථාපනය කරන්න"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"යෙදුම අස්ථාපනය කරන්න"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"යෙදුම් විස්තර"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 යෙදුමක් තෝරා ඇත"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 විජටයක් තෝරා ඇත"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ෆෝල්ඩරයක් තෝරා ඇත"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 කෙටිමඟක් තෝරා ඇත"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"කෙටිමං ස්ථාපනය කරන්න"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"පරිශීලක මැදිහත්වීමෙන් තොරව කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"කෙටිමං අස්ථාපනය කරන්න"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"පරිශීලකයාගේ මැදිහත්වීමෙන් තොරව කෙටිමං ඉවත් කිරීමට යෙදුමකට අවසර දෙයි."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"මුල් පිටු සැකසීම් සහ කෙටිමං කියවන්න"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"මුල් පිටුවේ ඇති සැකසීම් සහ කෙටිමං කියවීමට යෙදුමකට අවසර දෙයි."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"මුල් පිටු සැකසීම් සහ කෙටිමං ලියන්න"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"මුල් පිටුවේ සැකසීම් සහ කෙටිමං ඉවත් කිරීමට යෙදුමට අවසර දෙයි."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"ගැටලු පූරණ විජට් එක"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"මෙය පද්ධති යෙදුමක් වන අතර අස්ථාපනය කළ නොහැක."</string>
+    <string name="dream_name" msgid="1530253749244328964">"රොකට් ආරම්භකය"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"නම් නොකළ ෆෝල්ඩරය"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"මුල් පිටු තිරය %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$d හි %1$d පිටුව"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"මුල් පිටු තිරය %2$d හි %1$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d හි %1$d යෙදුම් පිටුව"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"විජට් පිටුව %2$d හි %1$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"සාදරයෙන් පිළිගනිමු"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"ගෙදර ඉන්නවා වගේ ඉන්න."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"යෙදුම් සහ ෆෝල්ඩර සඳහා තවත් තිර සාදන්න"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"ඔබේ යෙදුම් නිරූපක පිටපත් කිරීම"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"ඔබගේ පැරණි මුල් තිර වල නිරූපක සහ ෆෝල්ඩර ආයාත කරන්නද?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"නිරූපක පිටපත් කරන්න"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"අලුතින් පටන්ගන්න"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"ඔබගේ ඉඩ සංවිධානය කරගන්න"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"බිතුපත, විජට් සහ සැකසීම් කළමනාකරණය කිරීමට පසුබිම ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"මෙන්න ෆෝල්ඩරයක්"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"මෙවැනි එකක් තැනීමට, යෙදුමක් තට්ටු කර අල්ලාගෙන සිටින්න, අනතුරුව එය තවත් එකක් උඩින් ගෙන යන්න."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"හරි"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ෆෝල්ඩරය විවෘත විය, <xliff:g id="WIDTH">%1$d</xliff:g> හි <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"ෆෝල්ඩරය වැසීමට ස්පර්ශ කරන්න"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"නැවත නම් කිරීම සුරැකීමට ස්පර්ශ කරන්න"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ෆෝල්ඩරය වසා ඇත"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"<xliff:g id="NAME">%1$s</xliff:g> වෙත ෆෝල්ඩරය නැවත නම් කෙරිණි"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"ෆෝල්ඩරය: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"විජට්"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"වෝල්පේපර"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"සැකසීම්"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"රැඳී සිටිමින්"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"බාගනිමින්"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ස්ථාපනය කරමින්"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"නොදනී"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ප්‍රතිස්ථාපනය කළේ නැත"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"සියල්ල ඉවත් කරන්න"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ඉවත් කරන්න"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"සොයන්න"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"මෙම යෙදුම ස්ථාපනය කර නොමැත"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"මෙම නිරුපකයට යෙදුම ස්ථාපනය කර නොමැත. ඔබට එය ඉවත් කළ හැක, හෝ යෙදුම් සඳහා සොයන්න සහ අතින් ස්ථාපනය කරන්න."</string>
+</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 8ca6d90..a003679 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Plocha"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Nastaviť tapetu"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Počet vybratých položiek: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Počet vybratých položiek: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Počet vybratých položiek: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Tapeta %1$d z %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Vybratá položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Odstrániť"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Vybrať obrázok"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Tapety"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Orezanie tapety"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Stiahnutá aplikácia je v núdzovom režime zakázaná"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Miniaplikácie"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Miniaplikácie"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobraziť pamäť"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Miniaplikácie"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Na plochách už nie je miesto."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Na tejto ploche už nie je miesto"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"V časti hotseat už nie je miesto."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Táto miniaplikácia je pre hotseat príliš veľká."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Na paneli Obľúbené položky už nie je miesto"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Táto miniaplikácia je príliš veľká pre panel Obľúbené položky"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol vytvorený."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol odstránený."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Odkaz <xliff:g id="NAME">%s</xliff:g> už existuje."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazov plochy"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Povoľuje aplikácii zmeniť nastavenia a odkazy na ploche."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problém s načítaním miniaplikácií"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Nastavenie"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikácia a nedá sa odinštalovať."</string>
     <string name="dream_name" msgid="1530253749244328964">"Raketomet"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Nepomenovaný priečinok"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stránka aplikácií %1$d z %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stránka miniaplikácií %1$d z %2$d"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Vitajte"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Cíťte sa tu ako doma."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Vytvorte viac obrazoviek pre aplikácie a priečinky"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopírovanie ikon aplikácií"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Chcete importovať ikony a priečinky zo starých plôch?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"SKOPÍROVAŤ IKONY"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"ZAČAŤ S PREDVOLENÝM ROZLOŽENÍM"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Usporiadajte svoj priestor"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Ak chcete spravovať tapetu, miniaplikácie a nastavenia, dotknite sa pozadia a podržte."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Vyberte niektoré aplikácie"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Ak chcete pridať aplikáciu na plochu, dotknite sa jej a podržte."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadia, miniaplikácie a nastavenia"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Ak si chcete pozadie prispôsobiť, klepnite naň a podržte ho"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ROZUMIEM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Tu je priečinok"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ak chcete vytvoriť takýto priečinok, dotknite sa príslušnej aplikácie a podržte ju. Potom ju presuňte na druhú aplikáciu."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Priečinok je uzavretý"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Priečinok bol premenovaný na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Miniaplikácie"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Nastavenia"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Čaká sa"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Sťahovanie"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Inštalácia"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Neznáme"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Nebolo obnovené"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstrániť všetky"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrániť"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Vyhľadať"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Táto aplikácia nie je nainštalovaná"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikácia, ktorú zastupuje táto ikona, nie je nainštalovaná. Ikonu môžete odstrániť alebo vyhľadajte aplikáciu a ručne ju nainštalujte."</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 02b91f6..9c5bebd 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Začetni zaslon"</string>
     <string name="uid_name" msgid="7820867637514617527">"Osnovne aplikacije sistema Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Nastavi ozadje"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Št. izbranih: %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Št. izbranih: %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Št. izbranih: %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Ozadje %1$d od %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Izbrano: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Izbriši"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Izberi sliko"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Ozadja"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Obrezovanje ozadja"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikacija ni nameščena."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Prenesena aplikacija je onemogočena v Varnem načinu"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Pripomočki"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Pripomočki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaži pomnilnik"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Pripomočki"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Na začetnih zaslonih ni več prostora."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Na tem začetnem zaslonu ni več prostora."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"V vrstici z ikonami ni več prostora."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Ta pripomoček je prevelik za vrstico z ikonami."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"V vrstici za priljubljene ni več prostora"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ta pripomoček je prevelik za vrstico s priljubljenimi"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je ustvarjena."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je bila odstranjena."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« že obstaja."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"zapis nastavitev in bližnjic na začetnem zaslonu"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Aplikaciji dovoli spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Težava pri nalaganju pripomočka"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Nastavitev"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"To je sistemska aplikacija in je ni mogoče odstraniti."</string>
     <string name="dream_name" msgid="1530253749244328964">"Raketno izstrelišče"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"SVEŽ ZAČETEK"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organizirajte svoj prostor"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Če želite upravljati ozadje, pripomočke in nastavitve, se dotaknite ozadja in ga pridržite."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Izberite nekaj aplikacij"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Če želite dodati aplikacijo na začetni zaslon, se je dotaknite in jo pridržite."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ozadja, pripomočki in nastavitve"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Za prilagajanje se dotaknite ozadja in ga pridržite"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"V REDU"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"To je mapa"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Če želite ustvariti mapo, podobno tej, se dotaknite aplikacije in jo pridržite, nato pa jo premaknite nad drugo."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"V redu"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mapa je zaprta"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mapa je preimenovana v <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Pripomočki"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Ozadja"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Nastavitve"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Čakanje"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Prenašanje"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Nameščanje"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Neznano"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ni obnovljen"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstrani vse"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrani"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Iskanje"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacija ni nameščena."</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija za to ikono ni nameščena. Lahko jo odstranite ali poiščete aplikacijo in to namestite ročno."</string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index c3cf1a0..421f8d3 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Почетна"</string>
     <string name="uid_name" msgid="7820867637514617527">"Основне Android апликације"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Подеси позадину"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Изабранo je %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Изабрана je %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Изабранo je %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Позадина %1$d од %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Изабрано је <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Избриши"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Изабери слику"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Позадине"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Опсецање позадине"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Апликација није инсталирана."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Преузета апликација је онемогућена у Безбедном режиму"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Виџети"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Нема више простора на почетним екранима."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Нема више простора на овом почетном екрану."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Нема више простора на траци актуелности."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Овај виџет је превелики за траку актуелности."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Нема више простора на траци Омиљено"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Виџет је превелик за траку Омиљено"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је направљена."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је уклоњена."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ већ постоји."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"уписивање подешавања и пречица на почетном екрану"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Дозвољава апликацији да мења подешавања и пречице на почетном екрану."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Проблем при учитавању виџета"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Подешавање"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ово је системска апликација и не може да се деинсталира."</string>
     <string name="dream_name" msgid="1530253749244328964">"Лансер ракета"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Неименовани директоријум"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ПОЧНИТЕ ИСПОЧЕТКА"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Организујте простор"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Додирните позадину и задржите да бисте управљали позадином, виџетима и подешавањима."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Изаберите неколико апликација"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Да бисте додали апликацију на почетни екран, додирните је и задржите."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Позадине, виџети и подешавања"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Додирните и задржите позадину да бисте прилагодили"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ВАЖИ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Ево једног директоријума"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Да бисте направили директоријум попут овога, додирните и задржите апликацију, па је превуците преко друге."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Потврди"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Директоријум је затворен"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Директоријум је преименован у <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Директоријум: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Позадине"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Подешавања"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Чека се"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Преузима се"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Инсталира се"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Није враћено"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Уклони све"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Уклони"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Претражи"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ова апликација није инсталирана"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Апликација за ову икону није инсталирана. Можете да је уклоните или да потражите апликацију и инсталирате је ручно."</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 050bc33..e149c9e 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Startskärm"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Ange bakgrund"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d har valts"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d har valts"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d har valts"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Bakgrund %1$d av %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> har valts"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Ta bort"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Välj bild"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Bakgrunder"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Beskär bakgrund"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Appen är inte installerad."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Den hämtade appen inaktiverades i säkert läge"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgetar"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgetar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Visa Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widgetar"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Det finns inte plats för mer på dina startsidor."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Det finns inte plats för mer på den här startskärmen."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Utrymmet på Hotseat är fullt."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Denna widget är för stor för Hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritfältet är fullt"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denna widget är för stor för favoritfältet"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Genvägen <xliff:g id="NAME">%s</xliff:g> har skapats."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Genvägen <xliff:g id="NAME">%s</xliff:g> har tagits bort."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Genvägen <xliff:g id="NAME">%s</xliff:g> finns redan."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"skriva inställningar och genvägar för startsidan"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Tillåter att appen ändrar inställningar och genvägar på startsidan."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Det gick inte att läsa in widgeten"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Konfiguration"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Det här är en systemapp som inte kan avinstalleras."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Namnlös mapp"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"BÖRJA OM"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organisera ditt utrymme"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Tryck länge på bakgrunden om du vill hantera bakgrundsbilder, widgetar och inställningar."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Välj några appar"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Om du vill lägga till en app på startskärmen trycker du länge på den."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Bakgrunder, widgetar och inställningar"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tryck länge på bakgrunden om du vill anpassa den"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Det här är en mapp"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Skapa en till mapp av det här slaget genom att trycka och hålla ned en app och sedan dra den ovanpå en annan."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Mappen är stängd"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Mappen har bytt namn till <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widgetar"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunder"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Inställningar"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Väntar"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Hämtas"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Installerar"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Okänt"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Inte återställt"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Ta bort alla"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Ta bort"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Sök"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Appen är inte installerad"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen för den här ikonen har inte installerats. Du kan ta bort den eller söka efter appen och installera den manuellt."</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 5434fb3..07d0913 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Mwanzo"</string>
     <string name="uid_name" msgid="7820867637514617527">"Programu Msingi za Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Weka mandhari"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d zimechaguliwa"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d zimechaguliwa"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d zimechaguliwa"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Mandhari %1$d ya %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> iliyochaguliwa"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Futa"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Chukua picha"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Mandhari"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Punguza mandhari"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Programu iliyopakuliwa imezimwa katika Hali Salama"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Wijeti"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Wijeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Onyesha Kumbukumbu"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Wijeti"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Hakuna nafasi zaidi kwenye skrini zako za Nyumbani."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Hakuna nafasi katika skrini hii ya Mwanzo."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Hakuna nafasi zaidi kwenye eneo kali."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Wijeti hii ni kubwa zaidi kwa eneo kali."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Hakuna nafasi zaidi katika treya ya Vipendeleo"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Wijeti hii ni kubwa mno kwa treya ya Vipendeleo"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" imeundwa."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" iliondolewa."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" la njia ya mkato tayari lipo."</string>
@@ -79,7 +68,7 @@
     <string name="cab_widget_selection_text" msgid="1833458597831541241">"Wijeti 1 imechaguliwa"</string>
     <string name="cab_folder_selection_text" msgid="7999992513806132118">"Folda 1 limechaguliwa"</string>
     <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Njia 1 ya mkato imechaguliwa"</string>
-    <string name="permlab_install_shortcut" msgid="5632423390354674437">"sakinisha njia za mkato"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"kuweka njia za mkato"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Huruhusu programu kuongeza njia za mkato bila mtumiaji kuingilia kati."</string>
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ondoa njia za mikato"</string>
     <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Huruhusu programu kuondoa njia za mikato bila mtumiaji kuingilia kati."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"andika mipangilio ya skrini ya Mwanzo na njia za mkato"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Huruhusu programu kubadilisha mipangilio na njia za mkato katika skrini ya Mwanzo."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Tatizo la kupakia wijeti"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Sanidi"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
     <string name="dream_name" msgid="1530253749244328964">"Kizinduzi cha Roketi"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Folda isiyo na jina"</string>
@@ -104,14 +94,15 @@
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Unda skrini zaidi za programu na folda"</string>
     <string name="migration_cling_title" msgid="9181776667882933767">"Nakili ikoni za programu yako"</string>
-    <string name="migration_cling_description" msgid="2752413805582227644">"Je, ungependa kuingiza ikoni na folda kutoka kwa skrini zako za Mwanzo za zamani?"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Je, ungependa kuingiza ikoni na folda kutoka kwenye skrini zako za Mwanzo za zamani?"</string>
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"NAKILI IKONI"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ANZA UPYA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Panga nafasi yako"</string>
-    <string name="workspace_cling_move_item" msgid="528201129978005352">"Gusa na ushikile mandharinyuma ili udhibiti mandhari, wijeti, na mipangilio."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Chagua programu kadhaa"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Ili kuongeza programu kwenye Skrini yako Kuu, iguse na uishikilie."</string>
-    <string name="folder_cling_title" msgid="3894908818693254164">"Folda hii hapa"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Gusa na ushikilie mandharinyuma ili udhibiti mandhari, wijeti, na mipangilio."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Mandhari, wijeti, na mipangilio"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Gusa na ushikilie mandhari ili uweke mapendeleo"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NIMEELEWA"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Hii ni folda"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ili kuunda kama hii, gusa na ushikilie programu, kisha ipitishe juu ya nyingine."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"SAWA"</string>
     <string name="folder_opened" msgid="94695026776264709">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -120,11 +111,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Folda imefungwa"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Folda imebadilishwa jina kuwa <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Wijeti"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Mandhari"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Mipangilio"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Inasubiri"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Inapakua"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Inasakinisha"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Yasiyojulikana"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Haijarejeshwa"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Ondoa Zote"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Ondoa"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Tafuta"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Programu hii haijasakinishwa"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Programu ya ikoni hii haijasakinishwa. Unaweza kuiondoa, au utafute programu na uisakinishe wewe mwenyewe."</string>
 </resources>
diff --git a/res/values-sw340dp-land/dimens.xml b/res/values-sw340dp-land/dimens.xml
deleted file mode 100644
index 7901dc4..0000000
--- a/res/values-sw340dp-land/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 201 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">50dp</dimen>
-</resources>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index 2ec2f14..15d5725 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -2,9 +2,6 @@
     <bool name="is_tablet">true</bool>
     <bool name="allow_rotation">true</bool>
 
-    <!-- Whether or not to use custom clings if a custom workspace layout is passed in -->
-    <bool name="config_useCustomClings">true</bool>
-
 <!-- DragController -->
     <integer name="config_flingToDeleteMinVelocity">-1000</integer>
 
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 8d6c7f4..28679be 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -23,4 +23,13 @@
     <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>
+
+<!-- Cling -->
+    <dimen name="cling_migration_logo_height">400dp</dimen>
+    <dimen name="cling_migration_logo_width">274dp</dimen>
+    <dimen name="cling_migration_bg_size">600dp</dimen>
+    <dimen name="cling_migration_bg_shift">-300dp</dimen>
+    <dimen name="cling_migration_content_margin">64dp</dimen>
+    <dimen name="cling_migration_content_width">280dp</dimen>
+
 </resources>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index 200c0a0..bcbbafd 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -18,33 +18,4 @@
 -->
 
 <resources>
-    <style name="ClingButton">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:paddingTop">10dp</item>
-        <item name="android:paddingBottom">15dp</item>
-        <item name="android:paddingLeft">35dp</item>
-        <item name="android:paddingRight">35dp</item>
-        <item name="android:text">@string/cling_dismiss</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:background">@drawable/cling_button_bg</item>
-    </style>
-    <style name="ClingTitleText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_marginBottom">5dp</item>
-        <item name="android:textSize">30sp</item>
-        <item name="android:textColor">#33B5E5</item>
-        <item name="android:shadowColor">#000000</item>
-        <item name="android:shadowDy">2</item>
-        <item name="android:shadowRadius">2.0</item>
-    </style>
-    <style name="ClingText">
-        <item name="android:textSize">22sp</item>
-        <item name="android:textColor">#FFFFFF</item>
-        <item name="android:shadowColor">#000000</item>
-        <item name="android:shadowDy">2</item>
-        <item name="android:shadowRadius">2.0</item>
-        <item name="android:lineSpacingMultiplier">1.1</item>
-    </style>
 </resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index 433a5d4..ca13db0 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -18,15 +18,8 @@
 <!-- AppsCustomize -->
     <integer name="apps_customize_widget_cell_count_x">4</integer>
     <integer name="apps_customize_widget_cell_count_y">2</integer>
-    <integer name="apps_customize_cling_focused_x">4</integer>
-    <integer name="apps_customize_cling_focused_y">2</integer>
 
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">100dip</dimen>
-
-<!-- Cling -->
-    <!-- The offset for the text in the cling -->
-    <dimen name="cling_text_block_offset_x">140dp</dimen>
-    <dimen name="cling_text_block_offset_y">80dp</dimen>
 </resources>
diff --git a/res/values-sw720dp-port/dimens.xml b/res/values-sw720dp-port/dimens.xml
index 9fe312b..6f594d5 100644
--- a/res/values-sw720dp-port/dimens.xml
+++ b/res/values-sw720dp-port/dimens.xml
@@ -19,12 +19,4 @@
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">40dp</dimen>
-
-    <integer name="apps_customize_cling_focused_x">2</integer>
-    <integer name="apps_customize_cling_focused_y">2</integer>
-
-<!-- Cling -->
-    <!-- The offset for the text in the cling -->
-    <dimen name="cling_text_block_offset_x">80dp</dimen>
-    <dimen name="cling_text_block_offset_y">160dp</dimen>
 </resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 9ae155b..8be9964 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -25,4 +25,9 @@
      the drag view should be offset from the position of the original view. -->
     <dimen name="dragViewOffsetX">0dp</dimen>
     <dimen name="dragViewOffsetY">0dp</dimen>
+
+<!-- Cling -->
+    <dimen name="cling_migration_content_margin">96dp</dimen>
+    <dimen name="cling_migration_content_width">320dp</dimen>
+
 </resources>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index b3afae3..71f0304 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -18,38 +18,6 @@
 -->
 
 <resources>
-<!-- Clings -->
-    <style name="ClingButton">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:paddingTop">10dp</item>
-        <item name="android:paddingBottom">15dp</item>
-        <item name="android:paddingLeft">35dp</item>
-        <item name="android:paddingRight">35dp</item>
-        <item name="android:text">@string/cling_dismiss</item>
-        <item name="android:textSize">20sp</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:background">@drawable/cling_button_bg</item>
-    </style>
-    <style name="ClingTitleText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_marginBottom">5dp</item>
-        <item name="android:textSize">32sp</item>
-        <item name="android:textColor">#49C0EC</item>
-        <item name="android:shadowColor">#000000</item>
-        <item name="android:shadowDy">2</item>
-        <item name="android:shadowRadius">2.0</item>
-    </style>
-    <style name="ClingText">
-        <item name="android:textSize">22sp</item>
-        <item name="android:textColor">#FFFFFF</item>
-        <item name="android:shadowColor">#000000</item>
-        <item name="android:shadowDy">2</item>
-        <item name="android:shadowRadius">2.0</item>
-        <item name="android:lineSpacingMultiplier">1.1</item>
-    </style>
-
 <!-- Workspace -->
     <style name="TabIndicator.AppsCustomize">
         <item name="android:paddingLeft">32dp</item>
@@ -58,11 +26,6 @@
         <item name="android:maxWidth">240dp</item>
     </style>
 
-    <!-- QSB Search / Drop Target bar -->
-    <style name="QSBBar">
-    </style>
-    <style name="SearchDropTargetBar">
-    </style>
     <style name="SearchButton">
     </style>
     <style name="DropTargetButtonContainer">
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
new file mode 100644
index 0000000..f3aef1c
--- /dev/null
+++ b/res/values-ta-rIN/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"லாஞ்சர்3"</string>
+    <string name="home" msgid="7658288663002113681">"முகப்பு"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android முக்கியப் பயன்பாடுகள்"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"இறக்கிய பயன்பாடு பாதுகாப்பு முறையில் முடக்கப்பட்டது"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"விட்ஜெட்கள்"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"விட்ஜெட்கள்"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"நினைவகத்தைக் காட்டு"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"விட்ஜெட்டைத் தேர்வுசெய்ய தொட்டுப் &amp; பிடிக்கவும்."</string>
+    <string name="market" msgid="2619650989819296998">"ஷாப்"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"உருப்படியை இந்த முகப்புத் திரையில் விட முடியவில்லை."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"உருவாக்குவதற்கு விட்ஜெட்டைத் தேர்வுசெய்யவும்"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"கோப்புறையின் பெயர்"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"கோப்புறைக்கு மறுபெயரிடு"</string>
+    <string name="rename_action" msgid="5559600076028658757">"சரி"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"ரத்துசெய்"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"முகப்புத் திரையில் சேர்"</string>
+    <string name="group_applications" msgid="3797214114206693605">"பயன்பாடுகள்"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"குறுக்குவழிகள்"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"விட்ஜெட்கள்"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"உங்கள் முகப்புத் திரைகளில் வேறு இடம் இல்லை."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"முகப்புத் திரையில் இடமில்லை."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"பிடித்தவை ட்ரேயில் இடமில்லை"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"பிடித்தவை ட்ரேவிற்கு விட்ஜெட் மிகவும் பெரியது"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி உருவாக்கப்பட்டது."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி அகற்றப்பட்டது."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி ஏற்கனவே உள்ளது."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"குறுக்குவழியைத் தேர்வுசெய்யவும்"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"பயன்பாட்டைத் தேர்வுசெய்யவும்"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"பயன்பாடுகள்"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"முகப்பு"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"அகற்று"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"நிறுவல் நீக்கு"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"அகற்று"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"நிறுவல் நீக்கு"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"பயன்பாட்டுத் தகவல்"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"தேடு"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"குரல் தேடல்"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"பயன்பாடுகள்"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"அகற்று"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"புதுப்பிப்பை நிறுவல் நீக்கு"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"பயன்பாட்டை நிறுவல் நீக்கு"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"பயன்பாட்டின் விவரங்கள்"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 பயன்பாடு தேர்ந்தெடுக்கப்பட்டது"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 விட்ஜெட் தேர்ந்தெடுக்கப்பட்டது"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 கோப்புறை தேர்ந்தெடுக்கப்பட்டது"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 குறுக்குவழி தேர்ந்தெடுக்கப்பட்டது"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"குறுக்குவழிகளை நிறுவுதல்"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"குறுக்குவழிகளை நிறுவல் நீக்குதல்"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளை அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"முகப்பின் அமைப்புகள் மற்றும் குறுக்குவழிகளைப் படித்தல்"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"முகப்பில் உள்ள அமைப்புகள் மற்றும் குறுக்குவழிகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"முகப்பின் அமைப்புகள் மற்றும் குறுக்குவழிகளை எழுதுதல்"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"முகப்பில் உள்ள அமைப்புகள் மற்றும் குறுக்குவழிகளை மாற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"விட்ஜெட்டை ஏற்றுவதில் சிக்கல்"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"இது அமைப்பு பயன்பாடு என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது."</string>
+    <string name="dream_name" msgid="1530253749244328964">"ராக்கெட் லாஞ்சர்"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"பெயரிடப்படாத கோப்புறை"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"முகப்புத் திரை %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"பக்கம் %1$d / %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"முகப்புத் திரை %1$d of %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"பயன்பாடுகளின் பக்கம் %1$d / %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"விட்ஜெட்களின் பக்கம் %1$d / %2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"வரவேற்கிறோம்"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"உங்களுக்கேற்ற முறையில் உருவாக்கவும்."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"பயன்பாடுகள் மற்றும் கோப்புறைகளுக்காகக் கூடுதல் திரைகளை உருவாக்கவும்"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"பயன்பாட்டின் ஐகான்களை நகலெடுக்கவும்"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"பழைய முகப்புத் திரைகளிலிருந்து ஐகான்களையும் கோப்புறைகளையும் இறக்குமதி செய்யவா?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ஐகான்களை நகலெடு"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"புதிதாகத் தொடங்கு"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"இடத்தை ஒழுங்கமைக்கவும்"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"வால்பேப்பர், விட்ஜெட்கள் மற்றும் அமைப்புகளை நிர்வகிப்பதற்கு பின்புலத்தைத் தொட்டுப் &amp; பிடிக்கவும்."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"இதோ கோப்புறை"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"இதுபோன்ற ஒன்றை உருவாக்கப் பயன்பாட்டைத் தொட்டுப் &amp; பிடிக்கவும், பிறகு அதை வேறொன்றிற்கு நகர்த்தவும்."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"சரி"</string>
+    <string name="folder_opened" msgid="94695026776264709">"திறக்கப்பட்டக் கோப்புறை, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"கோப்புறையை மூட, தொடவும்"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"மறுபெயரிட்டதைச் சேமிக்க, தொடவும்"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"கோப்புறை மூடப்பட்டது"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"கோப்புறை <xliff:g id="NAME">%1$s</xliff:g> என மறுபெயரிடப்பட்டது"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"கோப்புறை: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"விட்ஜெட்கள்"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"வால்பேப்பர்கள்"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"அமைப்புகள்"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"காத்திருக்கிறது"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"பதிவிறக்குகிறது"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"நிறுவுகிறது"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"தெரியாதது"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"மீட்டெடுக்க முடியாது"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"அனைத்தையும் அகற்று"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"அகற்று"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"தேடு"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"பயன்பாடு நிறுவப்படவில்லை"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ஐகானுக்கான பயன்பாடு நிறுவப்படவில்லை. இதை அகற்றலாம் அல்லது பயன்பாட்டைத் தேடி கைமுறையாக நிறுவலாம்."</string>
+</resources>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
new file mode 100644
index 0000000..b48d6b8
--- /dev/null
+++ b/res/values-te-rIN/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"లాంచర్3"</string>
+    <string name="home" msgid="7658288663002113681">"హోమ్"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Android ప్రధాన అనువర్తనాలు"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"సురక్షిత మోడ్‌లో డౌన్‌లోడ్ చేసిన అనువర్తనం నిలిపివేయబడింది"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"విడ్జెట్‌లు"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"విడ్జెట్‌లు"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"మెమరీ చూపు"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"విడ్జెట్‌ను ఎంచుకోవడానికి తాకి &amp; నొక్కి పెట్టండి."</string>
+    <string name="market" msgid="2619650989819296998">"షాపింగ్ చేయి"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"ఈ హోమ్ స్క్రీన్‌లో అంశాన్ని వదలడం సాధ్యపడలేదు."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"సృష్టించాల్సిన విడ్జెట్ ఎంచుకోండి"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"ఫోల్డర్ పేరు"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"ఫోల్డర్‌ పేరు మార్చండి"</string>
+    <string name="rename_action" msgid="5559600076028658757">"సరే"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"రద్దు చేయి"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
+    <string name="group_applications" msgid="3797214114206693605">"అనువర్తనాలు"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"సత్వరమార్గాలు"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"విడ్జెట్‌లు"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"మీ హోమ్ స్క్రీన్‌ల్లో ఖాళీ లేదు."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"ఈ హోమ్ స్క్రీన్‌లో ఖాళీ లేదు."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"ఇష్టమైనవి ట్రేలో ఖాళీ లేదు"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"ఇష్టమైనవి ట్రే కోసం ఈ విడ్జెట్ చాలా పెద్దదిగా ఉంది"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" సృష్టించబడింది."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" తీసివేయబడింది."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" ఇప్పటికే ఉంది."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"సత్వరమార్గాన్ని ఎంచుకోండి"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"అనువర్తనాన్ని ఎంచుకోండి"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"అనువర్తనాలు"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"హోమ్"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"తీసివేయి"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"అన్ఇన్‌స్టాల్ చేయి"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"తీసివేయి"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"అన్ఇన్‌స్టాల్ చేయి"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"అనువర్తన సమాచారం"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"శోధించు"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"వాయిస్ శోధన"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"అనువర్తనాలు"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"తీసివేయి"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"నవీకరణను అన్‌ఇన్‌స్టాల్ చేయి"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"అనువర్తనాన్ని అన్‌ఇన్‌స్టాల్ చేయి"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"అనువర్తన వివరాలు"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 అనువర్తనం ఎంచుకోబడింది"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 విడ్జెట్ ఎంచుకోబడింది"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ఫోల్డర్ ఎంచుకోబడింది"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 సత్వరమార్గం ఎంచుకోబడింది"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"సత్వరమార్గాలను అన్ఇన్‌స్టాల్ చేయడం"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను వ్రాయడం"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"విడ్జెట్‌ను లోడ్ చేయడంలో సమస్య"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"ఇది సిస్టమ్ అనువర్తనం మరియు దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడదు."</string>
+    <string name="dream_name" msgid="1530253749244328964">"రాకెట్ లాంచర్"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"పేరు లేని ఫోల్డర్"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"హోమ్ స్క్రీన్ %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$dలో %1$dవ పేజీ"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dలో %1$dవ హోమ్ స్క్రీన్"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$dలో %1$dవ అనువర్తనాల పేజీ"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$dలో %1$dవ విడ్జెట్‌‌ల పేజీ"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"స్వాగతం"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"మీ స్వంత స్థలంగా భావించండి."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"అనువర్తనాలు మరియు ఫోల్డర్‌ల కోసం మరిన్ని స్క్రీన్‌లు సృష్టి."</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"మీ అనువర్తన చిహ్నాలను కాపీ చేయండి"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"మీ పాత హోమ్ స్క్రీన్‌ల నుండి చిహ్నాలు మరియు ఫోల్డర్‌లను దిగుమతి చేయాలా?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"చిహ్నాలను కాపీ చేయి"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"తాజాగా ప్రారంభించు"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"మీ స్థలాన్ని నిర్వహించండి"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"వాల్‌., విడ్జె., సెట్టి. నిర్వ. నేపథ్యం తాకి &amp; నొక్కి పెట్టండి."</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"ఇక్కడ ఫోల్డర్ ఉంది"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"ఇలాంటిది సృష్టించడానికి అనువర్తనాన్ని తాకి &amp; నొక్కి పెట్టండి, ఆపై మరోదాని పైన ఉంచండి."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"సరే"</string>
+    <string name="folder_opened" msgid="94695026776264709">"ఫోల్డర్ తెరవబడింది, <xliff:g id="WIDTH">%1$d</xliff:g> X <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"ఫోల్డర్‌ను మూసివేయడానికి తాకండి"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"పేరు మార్పును సేవ్ చేయడానికి తాకండి"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"ఫోల్డర్ మూసివేయబడింది"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"ఫోల్డర్ పేరు <xliff:g id="NAME">%1$s</xliff:g>గా మార్చబడింది"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"ఫోల్డర్: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"విడ్జెట్‌లు"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"వాల్‌పేపర్‌లు"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"సెట్టింగ్‌లు"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"వేచి ఉంది"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"డౌన్‌లోడ్ చేస్తోంది"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"ఇన్‌స్టాల్ చేస్తోంది"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"పునరుద్ధరించబడలేదు"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"అన్నీ తీసివేయి"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"శోధించు"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ఈ అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ చిహ్నం యొక్క అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ అనువర్తనం కోసం శోధించి దాన్ని మాన్యువల్‌గా ఇన్‌స్టాల్ చేయవచ్చు."</string>
+</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 2b7b8f3..beed898 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -21,21 +21,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
     <string name="home" msgid="7658288663002113681">"หน้าแรก"</string>
-    <string name="uid_name" msgid="7820867637514617527">"แอปหลักของแอนดรอยด์"</string>
+    <string name="uid_name" msgid="7820867637514617527">"แอปหลักของ Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"ตั้งค่าวอลเปเปอร์"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"เลือกไว้ %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"เลือกไว้ %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"เลือกไว้ %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"วอลเปเปอร์ %1$d จาก %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"เลือก <xliff:g id="LABEL">%1$s</xliff:g> แล้ว"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"ลบ"</string>
-    <string name="pick_image" msgid="1272073934062909527">"เลือกภาพ"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"วอลเปเปอร์"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"ครอบตัดวอลล์เปเปอร์"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"ไม่ได้ติดตั้งแอป"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"แอปที่ดาวน์โหลดถูกปิดในโหมดปลอดภัย"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"วิดเจ็ต"</string>
     <string name="widget_adder" msgid="3201040140710381657">"วิดเจ็ต"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"วิดเจ็ต"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"ไม่มีที่ว่างในหน้าจอหลักของคุณ"</string>
     <string name="out_of_space" msgid="4691004494942118364">"ไม่มีที่ว่างในหน้าจอหลักนี้"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"ไม่มีที่ว่างใน hotseat"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"วิดเจ็ตนี้มีขนาดใหญ่เกินไปสำหรับ hotseat"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"ไม่มีพื้นที่เหลือในถาดรายการโปรด"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"วิดเจ็ตนี้มีขนาดใหญ่เกินไปสำหรับถาดรายการโปรด"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"สร้างทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" แล้ว"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"นำทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" ออกแล้ว"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"มีทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" อยู่แล้ว"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"เขียนการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"อนุญาตให้แอปเปลี่ยนการตั้งค่าและทางลัดในหน้าแรก"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"มีปัญหาขณะโหลดวิดเจ็ต"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"ตั้งค่า"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"นี่เป็นแอประบบและไม่สามารถถอนการติดตั้งได้"</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"โฟลเดอร์ที่ไม่มีชื่อ"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"เริ่มต้นใหม่"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"จัดระเบียบพื้นที่ของคุณ"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"แตะพื้นหลังค้างไว้เพื่อจัดการวอลเปเปอร์ วิดเจ็ต และการตั้งค่า"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"เลือกบางแอป"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"หากต้องการเพิ่มแอปลงในหน้าจอหลัก ให้แตะแอปค้างไว้"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"วอลเปเปอร์ วิดเจ็ต และการตั้งค่า"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"แตะพื้นหลังค้างไว้เพื่อกำหนดค่า"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"รับทราบ"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"นี่คือโฟลเดอร์"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"หากต้องการสร้างโฟลเดอร์ลักษณะนี้ แตะแอปค้างไว้ แล้วย้ายไปทับอีกแอปหนึ่ง"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"ตกลง"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"โฟลเดอร์ปิดอยู่"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"เปลี่ยนชื่อโฟลเดอร์เป็น <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"วิดเจ็ต"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"วอลเปเปอร์"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"การตั้งค่า"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"กำลังรอ"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"กำลังดาวน์โหลด"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"กำลังติดตั้ง"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"ไม่รู้จัก"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"ไม่ได้คืนค่า"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"ลบทั้งหมด"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ลบ"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"ค้นหา"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"ไม่ได้ติดตั้งแอปนี้"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ยังไม่ได้ติดตั้งแอปสำหรับไอคอนนี้ คุณสามารถนำไอคอนออก หรือค้นหาแอปดังกล่าวแล้วติดตั้งด้วยตนเอง"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 536f0aa..7c6acd2 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Home"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Itakda ang wallpaper"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d ang napili"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d ang napili"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d ang napili"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Wallpaper %1$d ng %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Napili ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Tanggalin"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Pumili ng larawan"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Mga Wallpaper"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"I-crop ang wallpaper"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Hindi naka-install ang app."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Naka-disable ang na-download na app sa Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Mga Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Mga Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ipakita ang Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Mga Widget"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Wala nang lugar sa iyong mga Home screen."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Wala nang lugar sa Home screen na ito."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Wala nang lugar sa hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Masyadong malaki ang widget na ito para sa hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Wala nang lugar sa tray ng Mga Paborito"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Masyadong malaki ang widget na ito para sa tray ng Mga Paborito"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Nagawa ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Inalis ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Umiiral na ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"magsulat ng mga setting at shortcut ng Home"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Pinapayagan ang app na baguhin ang mga setting at shortcut sa Home."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problema sa pag-load ng widget"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"I-setup"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Isa itong app ng system at hindi maaaring i-uninstall."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Walang Pangalang Folder"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"MAGSIMULA NANG BAGO"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Ayusin ang iyong espasyo"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Pindutin nang matagal ang background upang pamahalaan ang wallpaper, mga widget at setting"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Pumili ng ilang apps"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Upang magdagdag ng app sa iyong Home screen, pindutin ito nang matagal."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Mga wallpaper, widget at setting"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pindutin nang matagal ang background upang i-customize"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NAKUHA KO"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Narito ang isang folder"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Upang gumawa ng katulad nito, pindutin nang matagal ang isang app, pagkatapos ay ilipat ito sa isa pang folder."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Nakasara ang folder"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Pinalitan ang pangalan ng folder ng <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Mga Widget"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Mga Wallpaper"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Mga Setting"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Naghihintay"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Nagda-download"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Nag-i-install"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Hindi kilala"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Hindi naibalik"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Alisin Lahat"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Alisin"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Maghanap"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Hindi naka-install ang app na ito"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Hindi naka-install ang app para sa icon na ito. Maaari mo itong alisin, o maaari mong hanapin ang app at i-install ito nang manu-mano."</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 4a4ee03..6c0bb69 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -23,24 +23,13 @@
     <string name="home" msgid="7658288663002113681">"Ana ekran"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android Çekirdek Uygulamaları"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Duvar kağıdını ayarla"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d tane seçildi"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d tane seçildi"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d tane seçildi"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Duvar kağıdı %1$d / %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> seçildi"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Sil"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Resim seç"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Duvar Kağıtları"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Duvar kağıdını kırp"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Uygulama yüklü değil."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"İndirilen uygulama Güvenli modda devre dışı bırakıldı"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget\'lar"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget\'lar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Belleği Göster"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget seçmek için dokunun ve basılı tutun."</string>
-    <string name="market" msgid="2619650989819296998">"Alışveriş yap"</string>
+    <string name="market" msgid="2619650989819296998">"Mağaza"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Öğe bu Ana ekrana bırakılamadı."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Oluşturmak için widget seçin"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Widget\'lar"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Ana ekranlarınızda yer kalmadı."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Bu Ana ekranda yer kalmadı."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Favori kısa yollarda yer yok"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Bu widget, favori kısa yollar için çok büyük."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoriler tepsisinde başka yer kalmadı"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Bu widget, Favoriler tepsisi için çok geniş"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu oluşturuldu."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu kaldırıldı."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu zaten var."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"Ana ekran ayarlarını ve kısayollarını yaz"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Uygulamaya, Ana ekrandaki ayarları ve kısayolları değiştirme izni verir."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Widget yüklenirken sorun oluştu"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Kurulum"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu bir sistem uygulamasıdır ve yüklemesi kaldırılamaz."</string>
     <string name="dream_name" msgid="1530253749244328964">"Roket Fırlatıcı"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Adsız Klasör"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Ana ekran %1$d / %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Uygulama sayfası %1$d / %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widget sayfası %1$d / %2$d"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Hoş geldiniz"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Rahatınıza bakın."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Uygulamalar ve klasörler için daha fazla ekran oluşturun"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"Uygulama simgelerini kopyala"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Eski Ana ekranlarınızdaki simgeler ve klasörler içe aktarılsın mı?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"SİMGELERİ KOPYALA"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"VARSAYILANI KULLAN"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Alanınızı düzenleyin"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Duvar kağıdını, widget\'ları ve ayarları yönetmek için arka plana uzun basın."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"İstediğiniz uygulamaları seçin"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Bir uygulamayı Ana ekranınıza eklemek için, ilgili uygulamayı basılı tutun."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Duvar kağıtları, widget\'lar ve ayarlar"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Özelleştirmek için arka plana dokunun ve basılı tutun"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"TAMAM"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"İşte bir klasör"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Buna benzer bir klasör oluşturmak için uygulamaya uzun basın ve sonra uygulamayı başka bir uygulamanın üzerine taşıyın."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"Tamam"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Klasör kapatıldı"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Klasörün adı <xliff:g id="NAME">%1$s</xliff:g> olarak değiştirildi"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Widget\'lar"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Duvar Kağıtları"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Ayarlar"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Bekliyor"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"İndiriliyor"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Yükleniyor"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Bilinmiyor"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Geri yüklenmedi"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Tümünü Kaldır"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Kaldır"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Ara"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Bu uygulama yüklü değil"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Bu simgenin uygulaması yüklü değil. Uygulamayı kaldırabilir veya arayıp manuel olarak yükleyebilirsiniz."</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 849e4cb..e5b5cd8 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Головний екран"</string>
     <string name="uid_name" msgid="7820867637514617527">"Базові програми Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Установити фон"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Вибрано %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Вибрано %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Вибрано %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Фоновий малюнок %1$d з %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"Вибрано <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Видалити"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Вибрати зображення"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Фонові малюнки"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Обрізати фоновий малюнок"</string>
-    <string name="activity_not_found" msgid="8071924732094499514">"Програму не встановлено."</string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Додаток видалено."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Завантажений додаток вимкнено в безпечному режимі"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Віджети"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Віджети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
@@ -49,19 +38,19 @@
     <string name="rename_action" msgid="5559600076028658757">"OК"</string>
     <string name="cancel_action" msgid="7009134900002915310">"Скасувати"</string>
     <string name="menu_item_add_item" msgid="1264911265836810421">"Додати на головний екран"</string>
-    <string name="group_applications" msgid="3797214114206693605">"Програми"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Додатки"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"Ярлики"</string>
     <string name="group_widgets" msgid="1569030723286851002">"Віджети"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"На головних екранах більше немає місця."</string>
     <string name="out_of_space" msgid="4691004494942118364">"На цьому головному екрані більше немає місця."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Немає вільного місця."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Цей віджет завеликий."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"В області \"Вибране\" немає місця"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Цей віджет завеликий для області \"Вибране\""</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" створено."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" вилучено."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" уже існує."</string>
     <string name="title_select_shortcut" msgid="6680642571148153868">"Вибрати ярлик"</string>
     <string name="title_select_application" msgid="3280812711670683644">"Вибрати програму"</string>
-    <string name="all_apps_button_label" msgid="9110807029020582876">"Програми"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Додатки"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Головний екран"</string>
     <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Вилучити"</string>
     <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Видалити"</string>
@@ -70,7 +59,7 @@
     <string name="info_target_label" msgid="8053346143994679532">"Про програму"</string>
     <string name="accessibility_search_button" msgid="1628520399424565142">"Пошук"</string>
     <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Голосовий пошук"</string>
-    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Програми"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Додатки"</string>
     <string name="accessibility_delete_button" msgid="6466114477993744621">"Вилучити"</string>
     <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Видалити оновлення"</string>
     <string name="cab_menu_delete_app" msgid="7435191475867183689">"Видалити програму"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"записувати налаштування та ярлики головного екрана"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Дозволяє програмі змінювати налаштування та ярлики на головному екрані."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Проблема із завантаженням віджета"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Налаштування"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Це системна програма, її неможливо видалити."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Папка без назви"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ПАНЕЛЬ ЗАПУСКУ ЗА УМОВЧАННЯМ"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Організуйте робочий простір"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Натисніть і утримуйте фон, щоб керувати фоновим малюнком, віджетами та налаштуваннями."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Виберіть програми"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Щоб додати програму на головний екран, торкніться й утримуйте її."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Фонові малюнки, віджети й налаштування"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Натисніть і втримуйте фон, щоб налаштувати робочу область"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ЗРОЗУМІЛО"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Це папка"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Щоб створити папку, натисніть і утримуйте програму, а потім перетягніть її на іншу."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OК"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Папку закрито"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Папку перейменовано на <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Папка <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Віджети"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Фонові малюнки"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Налаштування"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Очікування"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Завантаження"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Встановлення"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Невідомо"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Не відновлено"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Видалити всі"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Видалити"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Шукати"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Цей додаток не встановлено"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Додаток для цього значка не встановлено. Можна видалити значок або знайти додаток і встановити його вручну."</string>
 </resources>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
new file mode 100644
index 0000000..33b502e
--- /dev/null
+++ b/res/values-ur-rPK/strings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
+    <string name="home" msgid="7658288663002113681">"ہوم"</string>
+    <string name="uid_name" msgid="7820867637514617527">"‏Android کور ایپس"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"ایپ انسٹال نہیں ہے۔"</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"ویجیٹس"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"ویجیٹس"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"‏Mem دکھائیں"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"کوئی ویجیٹ منتخب کرنے کیلئے ٹچ کریں اور پکڑے رہیں۔"</string>
+    <string name="market" msgid="2619650989819296998">"خریداری کریں"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"آئٹم کو اس ہوم اسکرین پر ڈراپ نہیں کیا جا سکا۔"</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"بنانے کیلئے ویجیٹ منتخب کریں"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"فولڈر کا نام"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"فولڈر کا نام تبدیل کریں"</string>
+    <string name="rename_action" msgid="5559600076028658757">"ٹھیک ہے"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"منسوخ کریں"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"ہوم اسکرین میں شامل کریں"</string>
+    <string name="group_applications" msgid="3797214114206693605">"ایپس"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"شارٹ کٹس"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"ویجیٹس"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"آپ کی ہوم اسکرینوں پر مزید کوئی گنجائش نہیں ہے۔"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"اس ہوم اسکرین پر مزید کوئی گنجائش نہیں ہے۔"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"پسندیدہ ٹرے میں مزید کوئی گنجائش نہیں ہے"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"یہ ویجیٹ پسندیدہ ٹرے کیلئے کافی بڑا ہے"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" بنایا گیا۔"</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" ہٹا دیا گیا۔"</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" پہلے سے موجود ہے۔"</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"شارٹ کٹ منتخب کریں"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"ایپ منتخب کریں"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"ایپس"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"ہوم"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ہٹائیں"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"اَن انسٹال کریں"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"ہٹائیں"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"اَن انسٹال کریں"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"ایپ کی معلومات"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"تلاش کریں"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"صوتی تلاش"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ایپس"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"ہٹائیں"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"اپ ڈیٹ اَن انسٹال کریں"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"ایپ کو اَن انسٹال کریں"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"ایپ کی تفصیلات"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 ایپ منتخب کی گئی"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ویجیٹ منتخب کیا گیا"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 فولڈر منتخب کیا گیا"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 شارٹ کٹ منتخب کیا گیا"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"شارٹ کٹس انسٹال کریں"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"کسی ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس شامل کرنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"شارٹ کٹس کو اَن انسٹال کریں"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس ہٹانے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"ہوم ترتیبات اور شارٹ کٹس کو پڑھیں"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"ہوم ترتیبات اور شارٹ کٹس کو لکھیں"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو تبدیل کرنے کی اجازت دیتا ہے۔"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"ویجیٹ کو لوڈ کرنے میں مسئلہ"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"یہ ایک سسٹم ایپ ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔"</string>
+    <string name="dream_name" msgid="1530253749244328964">"راکٹ لانچر"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"بلا نام فولڈر"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"‏ہوم اسکرین ‎%1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"‏صفحہ ‎%1$d از ‎%2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"‏ہوم اسکرین ‎%1$d از ‎%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"‏ایپس کا صفحہ ‎%1$d از ‎%2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"‏ویجیٹس کا صفحہ ‎%1$d از ‎%2$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"خوش آمدید"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"ہوم سکرین مرضی کے مطابق بنائیں۔"</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ایپس اور فولڈرز کیلئے مزید اسکرینیں بنائیں"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"اپنے ایپ آئیکنز کو کاپی کریں"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"اپنی پرانی ہوم اسکرینوں سے آئیکنز اور فولڈرز درآمد کریں؟"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"آئیکنز کاپی کریں"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"نئے سرے سے شروع کریں"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"اپنی جگہ کو منظم کریں"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"وال پیپر، ویجیٹس اور ترتیبات کا نظم کرنے کیلئے پس منظر کو ٹچ کریں اور پکڑ کر رکھیں۔"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"یہ ہے ایک فولڈر"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"اس طرح کا ایک بنانے کیلئے، کسی ایپ کو ٹچ کریں اور پکڑ کر رکھیں، پھر اسے کسی دوسرے میں منتقل کریں۔"</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"ٹھیک ہے"</string>
+    <string name="folder_opened" msgid="94695026776264709">"فولڈر کھولا گیا، <xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"فولڈر بند کرنے کیلئے ٹچ کریں"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"نام کی تبدیلی محفوظ کرنے کیلئے ٹچ کریں"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"فولڈر بند ہو گیا"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"فولڈر کا نام تبدیل کر کے <xliff:g id="NAME">%1$s</xliff:g> کر دیا گیا"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"فولڈر: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"ویجیٹس"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"وال پیپرز"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"ترتیبات"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"منتظر"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"ڈاؤن لوڈ کیا جا رہا ہے"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"انسٹال کیا جا رہا ہے"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"نامعلوم"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"بحال نہیں ہوا"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"سبھی کو ہٹا دیں"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"ہٹائیں"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"تلاش کریں"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"یہ ایپ انسٹال کردہ نہیں ہے"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"اس آئیکن کیلئے ایپ انسٹال کردہ نہیں ہے۔ آپ اسے ہٹا سکتے ہیں یا ایپ کو تلاش کر سکتے اور دستی طور پر اسے انسٹال کر سکتے ہیں۔"</string>
+</resources>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
new file mode 100644
index 0000000..791f6c8
--- /dev/null
+++ b/res/values-uz-rUZ/strings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="5181331383435256801">"Ishga tushirgich3"</string>
+    <string name="home" msgid="7658288663002113681">"Uy"</string>
+    <string name="uid_name" msgid="7820867637514617527">"Androidga asoslangan dasturlar"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Ilova o‘rnatilmadi."</string>
+    <!-- no translation found for safemode_shortcut_error (9160126848219158407) -->
+    <skip />
+    <string name="widgets_tab_label" msgid="2921133187116603919">"Vidjetlar"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"Vidjetlar"</string>
+    <string name="toggle_weight_watcher" msgid="5645299835184636119">"Xotirani ko‘rsatish"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidjetni tanlash uchun bosib turing."</string>
+    <string name="market" msgid="2619650989819296998">"Do‘kon"</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementni ushbu \"Uy\" ekraniga tashlab bo‘lmadi."</string>
+    <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Yaratish uchun vidjet tanlang"</string>
+    <string name="rename_folder_label" msgid="3727762225964550653">"Jild nomi"</string>
+    <string name="rename_folder_title" msgid="3771389277707820891">"Jild nomini o‘zgartirish"</string>
+    <string name="rename_action" msgid="5559600076028658757">"OK"</string>
+    <string name="cancel_action" msgid="7009134900002915310">"Bekor qilish"</string>
+    <string name="menu_item_add_item" msgid="1264911265836810421">"Uy ekraniga qo‘shish"</string>
+    <string name="group_applications" msgid="3797214114206693605">"Ilovalar"</string>
+    <string name="group_shortcuts" msgid="6012256992764410535">"Yorliqlar"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"Vidjetlar"</string>
+    <string name="completely_out_of_space" msgid="6106288382070760318">"Uy ekraningizda birorta ham xona yo‘q."</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Uy ekranida bitta ham xona yo‘q."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Ajratilganlarda birorta ham xona yo‘q"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ajratilganlar uchun ushbu vidjet juda katta"</string>
+    <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i yaratildi."</string>
+    <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i o‘chirildi."</string>
+    <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i allaqachon mavjud."</string>
+    <string name="title_select_shortcut" msgid="6680642571148153868">"Yorliqni tanlash"</string>
+    <string name="title_select_application" msgid="3280812711670683644">"Ilovani tanlash"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Ilovalar"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Uy"</string>
+    <string name="delete_zone_label_workspace" msgid="4009607676751398685">"O‘chirish"</string>
+    <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"O‘chirish"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"O‘chirish"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"O‘chirish"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Ilova ma’lumoti"</string>
+    <string name="accessibility_search_button" msgid="1628520399424565142">"Izlash"</string>
+    <string name="accessibility_voice_search_button" msgid="4637324840434406584">"Ovozli qidiruv"</string>
+    <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Ilovalar"</string>
+    <string name="accessibility_delete_button" msgid="6466114477993744621">"O‘chirish"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Yangilashni o‘chirish"</string>
+    <string name="cab_menu_delete_app" msgid="7435191475867183689">"Ilovani o‘chirish"</string>
+    <string name="cab_menu_app_info" msgid="8593722221450362342">"Ilova ma’lumotlari"</string>
+    <string name="cab_app_selection_text" msgid="374688303047985416">"1 ta ilova tanlandi"</string>
+    <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ta vidjet tanlandi"</string>
+    <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ta jild tanlandi"</string>
+    <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ta yorliq tanlandi"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"yorliqlar o‘rnatish"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi."</string>
+    <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"yorliqlarni o‘chirish"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ilovaga foydalanuvchiga bildirmasdan yorliqlarni o‘chirish uchun ruxsat beradi."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"Uy sozlamalari va yorliqlarini o‘qish"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalarni o‘qish uchun ruxsat beradi."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"Uy sozlamalari va yorliqlarini yozish"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalrni o‘zgartirish uchun ruxsat beradi."</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Vidjetni yuklashda muammo"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi."</string>
+    <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Nomsiz jild"</string>
+    <string name="workspace_description_format" msgid="2950174241104043327">"Uy ekrani %1$d"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%2$ddan %1$d ta sahifa"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Uy ekrani %2$ddan %1$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ilovalar sahifasi %2$ddan %1$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Vidjetlar sahifasi %2$ddan %1$d"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Xush kelibsiz"</string>
+    <string name="first_run_cling_description" msgid="6447072552696253358">"O‘zingizni uyingizdagidek his qiling."</string>
+    <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
+    <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Ilovalar va jildlar uchun ko‘proq ekranlar yaratish"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Ilovangiz nishonchalaridan nusxa olish"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Eski \"Uy\" ekranlaringizdan jildlar va nishonchalar import qilinsinmi?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"NISHONCHALARNI NUSXALASH"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"YANGIDAN BOSHLASH"</string>
+    <string name="workspace_cling_title" msgid="5626202359865825661">"Joylaringizni boshqaring"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"Fon rasmi, vidjet va sozlamalarni boshqarish uchun orqa fonga bosib turing"</string>
+    <string name="folder_cling_title" msgid="3894908818693254164">"Mana sizga jild"</string>
+    <string name="folder_cling_create_folder" msgid="6158215559475836131">"Bunga o‘xshaganini yaratish uchun bosib turing, keyin boshqasiga o‘ting."</string>
+    <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Jild ochildi, <xliff:g id="WIDTH">%1$d</xliff:g> ga <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Jildni yopish uchun bosing"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"O‘zgartirilgan nomni saqlash uchun bosing"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Jild yopildi"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Jild nomi <xliff:g id="NAME">%1$s</xliff:g>ga o‘zgartirildi"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Jild: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Vidjetlar"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Orqa fon rasmlari"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Sozlamalar"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Kutilmoqda"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Yuklab olinmoqda"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"O‘rnatilmoqda"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Noma’lum"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Qayta tiklanmadi"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Barchasini o‘chirish"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"O‘chirish"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Qidirish"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ushbu ilova o‘rnatilmagan"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ilova o‘rnatilmagan. Belgini o‘chirib tashlashingiz yoki ilovani topib, uni qo‘lda o‘rnatishingiz mumkin."</string>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 0274e7d..4891230 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Màn hình chính"</string>
     <string name="uid_name" msgid="7820867637514617527">"Ứng dụng lõi Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Đặt hình nền"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"Đã chọn %1$d"</item>
-    <item quantity="one" msgid="142482526010824029">"Đã chọn %1$d"</item>
-    <item quantity="other" msgid="1418352074806573570">"Đã chọn %1$d"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Hình nền %1$d / %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"<xliff:g id="LABEL">%1$s</xliff:g> được chọn"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Xóa"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Chọn hình ảnh"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Hình nền"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Cắt hình nền"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Ứng dụng chưa được cài đặt."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ứng dụng đã tải xuống bị tắt ở chế độ An toàn"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Tiện ích con"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Tiện ích con"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Hiển thị bộ nhớ"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Tiện ích con"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Không còn chỗ trên Màn hình chính của bạn."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Không còn chỗ trên Màn hình chính này."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Không còn chỗ trên vùng gắn."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Tiện ích con này quá lớn cho vùng gắn."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Không còn chỗ trong khay Mục yêu thích"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tiện ích con này có kích thước quá lớn để đặt vào khay Mục yêu thích"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã được tạo."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã bị xóa."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã tồn tại."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"ghi cài đặt và lối tắt trên Màn hình chính"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Cho phép ứng dụng thay đổi cài đặt và lối tắt trên Màn hình chính."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Sự cố khi tải tiện ích con"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Thiết lập"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Thư mục chưa đặt tên"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"BẮT ĐẦU LÀM MỚI"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Sắp xếp không gian của bạn"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Chạm và giữ nền để quản lý hình nền, tiện ích con và cài đặt."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Chọn một số ứng dụng"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Để thêm ứng dụng vào Màn hình chính của bạn, chạm và giữ ứng dụng đó."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Hình nền, tiện ích và cài đặt"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Chạm và giữ nền để tùy chỉnh"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Đây là một thư mục"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Để tạo thư mục như thế này, hãy chạm và giữ một ứng dụng, sau đó di chuyển ứng dụng đó lên trên một ứng dụng khác."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Đã đóng thư mục"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Đã đổi tên thư mục thành <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Tiện ích con"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Hình nền"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Cài đặt"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Đang đợi"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Đang tải xuống"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Đang cài đặt"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Không được khôi phục"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Xóa tất cả"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Xóa"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Tìm kiếm"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ứng dụng này chưa được cài đặt"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ứng dụng cho biểu tượng này chưa được cài đặt. Bạn có thể xóa ứng dụng hoặc tìm kiếm và cài đặt ứng dụng theo cách thủ công."</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f38a6f4..3365581 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"主屏"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android 核心应用"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"设置壁纸"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"已选择%1$d项"</item>
-    <item quantity="one" msgid="142482526010824029">"已选择%1$d项"</item>
-    <item quantity="other" msgid="1418352074806573570">"已选择%1$d项"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"第%1$d张壁纸,共%2$d张"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"已选择<xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"删除"</string>
-    <string name="pick_image" msgid="1272073934062909527">"选择图片"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"壁纸"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"剪裁壁纸"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"未安装该应用。"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"安全模式下不允许使用下载的此应用"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"小部件"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"小部件"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"您的主屏幕上没有空间了。"</string>
     <string name="out_of_space" msgid="4691004494942118364">"此主屏幕上已没有空间。"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"底部区域已无空间。"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"该小部件太大,底部区域容纳不下。"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"收藏栏已满"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"该小部件太大,收藏栏中放不下"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"已创建“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"写入主屏幕设置和快捷方式"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"允许应用更改主屏幕中的设置和快捷方式。"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"加载小部件时出现问题"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"设置"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"这是系统应用,无法卸载。"</string>
     <string name="dream_name" msgid="1530253749244328964">"火箭发射器"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"未命名文件夹"</string>
@@ -96,24 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"主屏幕:第%1$d屏,共%2$d屏"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"应用:第%1$d页,共%2$d页"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"小部件:第%1$d页,共%2$d页"</string>
-    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
-    <skip />
+    <string name="first_run_cling_title" msgid="2459738000155917941">"欢迎使用"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"您的主屏幕您做主。"</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"添加更多屏幕来容纳应用和文件夹"</string>
-    <!-- no translation found for migration_cling_title (9181776667882933767) -->
-    <skip />
-    <!-- no translation found for migration_cling_description (2752413805582227644) -->
-    <skip />
-    <!-- no translation found for migration_cling_copy_apps (946331230090919440) -->
-    <skip />
-    <!-- no translation found for migration_cling_use_default (2626475813981258626) -->
-    <skip />
+    <string name="migration_cling_title" msgid="9181776667882933767">"复制应用图标"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"要导入旧的主屏幕中的图标和文件夹吗?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"复制图标"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"使用全新配置"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"整理您的空间"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"触摸并按住背景,即可管理壁纸、小部件和设置。"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"选择一些应用"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"要将应用添加到主屏幕,请触摸并按住该应用。"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"壁纸、小部件和设置"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"触摸并按住背景,即可进行个性化设置"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"这是一个文件夹"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"要创建一个类似的文件夹,请触摸并按住某个应用,然后将其移至另一个应用上。"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"确定"</string>
@@ -123,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"文件夹已关闭"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"已将文件夹重命名为“<xliff:g id="NAME">%1$s</xliff:g>”"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"小部件"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"壁纸"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"设置"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"正在等待"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"正在下载"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"正在安装"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"未知"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"无法还原"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"搜索"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"未安装此应用"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"未安装此图标对应的应用。您可以移除此图标,也可以尝试搜索相应的应用并手动安装。"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index cc79cfd0..457d5be 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"主畫面"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android 核心應用程式"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"設定桌布"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"已選取 %1$d 個"</item>
-    <item quantity="one" msgid="142482526010824029">"已選取 %1$d 個"</item>
-    <item quantity="other" msgid="1418352074806573570">"已選取 %1$d 個"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"第 %1$d 張桌布,共 %2$d 張"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"已選取「<xliff:g id="LABEL">%1$s</xliff:g>」"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"刪除"</string>
-    <string name="pick_image" msgid="1272073934062909527">"選擇圖片"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"桌布"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"裁剪桌布"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"尚未安裝應用程式。"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"在安全模式中無法使用「已下載的應用程式」功能"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"小工具"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"主畫面已無空間。"</string>
     <string name="out_of_space" msgid="4691004494942118364">"主畫面已無空間。"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"停駐區已無可用空間。"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"這個小工具過大,停駐區沒有足夠空間。"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"我的收藏寄存區沒有足夠空間"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"這個小工具過大,我的收藏寄存區沒有足夠空間"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"已建立「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已存在。"</string>
@@ -80,14 +69,15 @@
     <string name="cab_folder_selection_text" msgid="7999992513806132118">"已選取 1 個資料夾"</string>
     <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"已選取 1 個捷徑"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"安裝捷徑"</string>
-    <string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式無需用戶許可也可新增捷徑。"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式無需使用者許可也可新增捷徑。"</string>
     <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"解除安裝捷徑"</string>
-    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"允許應用程式無需用戶許可也可移除捷徑。"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"允許應用程式無需使用者許可也可移除捷徑。"</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"讀取主畫面的設定和捷徑"</string>
     <string name="permdesc_read_settings" msgid="5833423719057558387">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"寫入主畫面的設定和捷徑"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"允許應用程式更改主畫面中的設定和捷徑。"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"載入小工具時發生問題"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"設定"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,無法將其解除安裝。"</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"重新開始"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"管理您的空間"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"輕觸並按住背景,即可管理桌布、小工具和設定。"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"選擇一些應用程式"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"輕觸並按住應用程式,即可加到主畫面。"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"桌布、小工具和設定"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"輕觸並按住背景即可自訂"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"資料夾顯示如下"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"如要建立類似的資料夾,請輕觸並按住某個應用程式,然後疊到另一個應用程式之上。"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"確定"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"已關閉資料夾"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"資料夾已重新命名為「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"等候中"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"下載中"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"安裝中"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"無法還原"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"尚未安裝這個應用程式"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"您尚未安裝這個圖示代表的應用程式。您可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index afac366..2d40059 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"主螢幕"</string>
     <string name="uid_name" msgid="7820867637514617527">"Android 核心應用程式"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"設定桌布"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"已選取 %1$d 個項目"</item>
-    <item quantity="one" msgid="142482526010824029">"已選取 %1$d 個項目"</item>
-    <item quantity="other" msgid="1418352074806573570">"已選取 %1$d 個項目"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"第 %1$d 張桌布,共 %2$d 張"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"已選取<xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"刪除"</string>
-    <string name="pick_image" msgid="1272073934062909527">"選擇圖片"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"桌布"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"裁剪桌布"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"應用程式未安裝。"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"在安全模式中無法使用「已下載的應用程式」功能"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"小工具"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"主螢幕已無空間。"</string>
     <string name="out_of_space" msgid="4691004494942118364">"這個主螢幕已無空間。"</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"停駐區已無空間。"</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"這個小工具過大,停駐區無法容納。"</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"「我的最愛」匣已無可用空間"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"這個小工具過大,「我的最愛」匣無法容納"</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"已建立「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已存在。"</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"寫入主螢幕設定和捷徑"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"允許應用程式變更主螢幕中的設定和捷徑。"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"載入小工具時發生問題"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"設定"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,不可解除安裝。"</string>
     <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"重新開始"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"管理您的空間"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"輕觸並按住背景,即可管理桌布、小工具和設定。"</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"選擇一些應用程式"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"如要將應用程式新增至主螢幕,請輕觸並按住目標。"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"桌布、小工具和設定"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"輕觸並按住背景即可自訂"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"資料夾顯示如下"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"如要建立類似的資料夾,請輕觸並按住應用程式,然後將應用程式疊放在另一個應用程式上。"</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"確定"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"資料夾已關閉"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"已將資料夾重新命名為「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"等待中"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"下載中…"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"安裝中"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"無法還原"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"尚未安裝這個應用程式"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"您尚未安裝這個圖示代表的應用程式。您可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 6bd8a41..89cd5cc 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -23,19 +23,8 @@
     <string name="home" msgid="7658288663002113681">"Ikhaya"</string>
     <string name="uid_name" msgid="7820867637514617527">"Izinhlelo zokusebenza ze-Android Core"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
-    <string name="wallpaper_instructions" msgid="563973358787555519">"Setha isithombe sangemuva"</string>
-  <plurals name="number_of_items_selected">
-    <item quantity="zero" msgid="7464587177007785408">"%1$d khethiwe"</item>
-    <item quantity="one" msgid="142482526010824029">"%1$d khethiwe"</item>
-    <item quantity="other" msgid="1418352074806573570">"%1$d khethiwe"</item>
-  </plurals>
-    <string name="wallpaper_accessibility_name" msgid="1655953108132967972">"Isithombe sangemuva se-%1$d of %2$d"</string>
-    <string name="announce_selection" msgid="8338254712932127413">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhethiwe"</string>
-    <string name="wallpaper_delete" msgid="8095005658756613921">"Susa"</string>
-    <string name="pick_image" msgid="1272073934062909527">"Thatha isithombe"</string>
-    <string name="pick_wallpaper" msgid="8179698221502010609">"Izithombe zangemuva"</string>
-    <string name="crop_wallpaper" msgid="8334345984491368009">"Nqampuna isithombe sangemuva"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Uhlelo lokusebenza olulandiwe lukhutshaziwe kumodi ephephile"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Amawijethi"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Amawijethi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Bonisa i-Mem"</string>
@@ -54,8 +43,8 @@
     <string name="group_widgets" msgid="1569030723286851002">"Amawijethi"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"Akusenagumbi ezikrinini zakho Zekhaya."</string>
     <string name="out_of_space" msgid="4691004494942118364">"Asisekho isikhala kulesi sikrini Sasekhaya."</string>
-    <string name="hotseat_out_of_space" msgid="9139760413395605841">"Akusenagumbi ku-hotseat."</string>
-    <string name="invalid_hotseat_item" msgid="1211534262129849507">"Le wijethi inkulu kakhulu ukuba ku-hotseat."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Asisekho isikhala kwitreyi lezintandokazi"</string>
+    <string name="invalid_hotseat_item" msgid="5779907847267573691">"Le wijethi inkulu kakhulu ukuba kwitreyi lezintandokazi."</string>
     <string name="shortcut_installed" msgid="1701742129426969556">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sidaliwe."</string>
     <string name="shortcut_uninstalled" msgid="8176767991305701821">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sisusiwe."</string>
     <string name="shortcut_duplicate" msgid="9167217446062498127">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sesivele sikhona."</string>
@@ -88,6 +77,7 @@
     <string name="permlab_write_settings" msgid="3574213698004620587">"bhala izilungiselelo zokuthi Ikhaya nezinqamuleli"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ivumela uhlelo lokusebenza ukuthi lushintshe izilungiselelo nezinqamuleli Ekhaya."</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Inkinga yokulayisha iwijethi"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Ukumisa"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
     <string name="dream_name" msgid="1530253749244328964">"Isiqalisi se-Rocket"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"Ifolda engenagama"</string>
@@ -107,8 +97,9 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"QALISA KABUSHA"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Hlela isikhala sakho"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Thinta uphinde ubambe okungemuva ukuze uphathe isithombe sangemuva, amawijethi nezilungiselelo."</string>
-    <string name="all_apps_cling_title" msgid="34929250753095858">"Khetha izinhlelo zokusebenza ezithile"</string>
-    <string name="all_apps_cling_add_item" msgid="400866858451850784">"Ukuze ungeze uhlelo lokusebenza kusikrini sakho se-Ikhaya, thinta futhi uyibambe."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Izithombe zangemuva, amawijethi, nezilungiselelo"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Thinta uphinde ubambe ingemuva ukuze wenze ngokwezifiso"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NGIYITHOLILE"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Nayi ifolda"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ukuze udale eyodwa efana nale, thinta uphinde ubambe uhlelo lokusebenza, bese ulidlulisa ngaphezulu kwelinye."</string>
     <string name="cling_dismiss" msgid="8962359497601507581">"KULUNGILE"</string>
@@ -118,11 +109,17 @@
     <string name="folder_closed" msgid="4100806530910930934">"Ifolda ivaliwe"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"Ifolda iqanjwe kabusha ngo-<xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
-    <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
-    <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
-    <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
     <string name="widget_button_text" msgid="2880537293434387943">"Amawijethi"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Izithombe zangemuva"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Izilungiselelo"</string>
+    <string name="package_state_enqueued" msgid="6227252464303085641">"Ilindile"</string>
+    <string name="package_state_downloading" msgid="4088770468458724721">"Iyalanda"</string>
+    <string name="package_state_installing" msgid="7588193972189849870">"Iyafaka"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Akwaziwa"</string>
+    <string name="package_state_error" msgid="7672093962724223588">"Ayibuyiselwe"</string>
+    <string name="abandoned_clean_all" msgid="5256770727689657618">"Susa konke"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Susa"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Sesha"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Lolu hlelo lokusebenza alifakiwe"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Uhlelo lokusebenza lalesi sithonjana alufakiwe. Ungalisusa, noma sesha uhlelo lokusebenza bese uzifakela lona ngokuzenzela."</string>
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 0006a74..65f8f22 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -25,17 +25,8 @@
         <attr name="sourceViewId" format="integer" />
     </declare-styleable>
 
-    <!-- Cling specific attributes. These attributes are used to customize
-         the cling in XML files. -->
-    <declare-styleable name="Cling">
-        <!-- Used to identify how to draw the cling bg -->
-        <attr name="drawIdentifier" format="string"  />
-    </declare-styleable>
-
-    <!-- Page Indicator specific attributes. These attributes are used to customize
-         the cling in XML files. -->
+    <!-- Page Indicator specific attributes. -->
     <declare-styleable name="PageIndicator">
-        <!-- Used to identify how to draw the cling bg -->
         <attr name="windowSize" format="integer"  />
     </declare-styleable>
 
@@ -98,16 +89,16 @@
         <!-- A spacing override for the icons within a page -->
         <attr name="pageLayoutWidthGap" format="dimension" />
         <attr name="pageLayoutHeightGap" format="dimension" />
-        <!-- The padding of the pages that are dynamically created per page -->
-        <attr name="pageLayoutPaddingTop" format="dimension" />
-        <attr name="pageLayoutPaddingBottom" format="dimension" />
-        <attr name="pageLayoutPaddingLeft" format="dimension" />
-        <attr name="pageLayoutPaddingRight" format="dimension" />
 
         <!-- The page indicator for this workspace -->
         <attr name="pageIndicator" format="reference" />
     </declare-styleable>
 
+    <declare-styleable name="BubbleTextView">
+        <!-- A spacing override for the icons within a page -->
+        <attr name="customShadows" format="boolean" />
+    </declare-styleable>
+
     <!-- AppsCustomizePagedView specific attributes.  These attributes are used to
          customize an AppsCustomizePagedView in xml files. -->
     <declare-styleable name="AppsCustomizePagedView">
@@ -123,10 +114,6 @@
         <attr name="widgetCountX" format="integer" />
         <!-- Number of widgets vertically -->
         <attr name="widgetCountY" format="integer" />
-        <!-- The x index of the item to be focused in the cling -->
-        <attr name="clingFocusedX" format="integer" />
-        <!-- The y index of the item to be focused in the cling -->
-        <attr name="clingFocusedY" format="integer" />
     </declare-styleable>
 
     <!-- XML attributes used by default_workspace.xml -->
@@ -151,9 +138,9 @@
         <attr name="workspace" format="reference" />
     </declare-styleable>
 
-    <!-- Only used in the device overlays -->
-    <declare-styleable name="CustomClingTitleText">
-    </declare-styleable>
-    <declare-styleable name="CustomClingText">
+    <declare-styleable name="PreloadIconDrawable">
+        <attr name="background" format="reference" />
+        <attr name="ringOutset" format="dimension" />
+        <attr name="indicatorSize" format="dimension" />
     </declare-styleable>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index ffee05f..29837ea 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -22,8 +22,10 @@
          over the delete target or the info target -->
     <color name="delete_target_hover_tint">#DAFF0000</color>
     <color name="info_target_hover_tint">#DA0099CC</color>
+    <color name="cling_scrim_background">#80000000</color>
 
     <color name="bubble_dark_background">#20000000</color>
+    <color name="focused_background">#80c6c5c5</color>
 
     <color name="appwidget_error_color">#FCCC</color>
 
@@ -31,10 +33,9 @@
     <color name="workspace_all_apps_and_delete_zone_text_shadow_color">#A0000000</color>
     <color name="workspace_icon_text_color">#FFF</color>
 
-    <color name="apps_customize_icon_text_color">#FFF</color>
-    <color name="folder_items_text_color">#FF333333</color>
-    <color name="folder_items_glow_color">#FFCCCCCC</color>
+    <color name="quantum_panel_text_color">#FF666666</color>
+    <color name="quantum_panel_text_shadow_color">#FFC4C4C4</color>
     <color name="outline_color">#FFFFFFFF</color>
-    
-    <color name="first_run_cling_circle_background_color">#64b1ea</color>
+    <color name="widget_text_panel">#FF374248</color>
+
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index b512ffe..96bd13b 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -17,12 +17,16 @@
     <!-- Max number of page indicators to show -->
     <integer name="config_maxNumberOfPageIndicatorsToShow">21</integer>
 
+    <!-- App data backup and restore. To enble backup, register with an android backup service.
+         http://developer.android.com/guide/topics/data/backup.html#BackupKey -->
+    <bool name="enable_backup">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">65</integer>
+    <integer name="config_workspaceScrimAlpha">55</integer>
     <integer name="config_workspaceUnshrinkTime">300</integer>
     <integer name="config_overviewTransitionTime">250</integer>
 
@@ -31,14 +35,20 @@
 
     <!-- Fade/zoom in/out duration & scale in the AllApps transition.
          Note: This should be less than the workspaceShrinkTime as they happen together. -->
+    <integer name="config_appsCustomizeRevealTime">220</integer>
     <integer name="config_appsCustomizeZoomInTime">350</integer>
     <integer name="config_appsCustomizeZoomOutTime">600</integer>
     <integer name="config_appsCustomizeZoomScaleFactor">7</integer>
     <integer name="config_appsCustomizeFadeInTime">250</integer>
     <integer name="config_appsCustomizeFadeOutTime">200</integer>
     <integer name="config_appsCustomizeWorkspaceShrinkTime">300</integer>
-    <integer name="config_appsCustomizeWorkspaceAnimationStagger">40</integer>
-    <integer name="config_workspaceAppsCustomizeAnimationStagger">100</integer>
+
+    <integer name="config_appsCustomizeConcealTime">250</integer>
+    <integer name="config_appsCustomizeItemsAlphaStagger">60</integer>
+
+    <!-- This constant stores the ratio of the all apps button drawable which
+         is used for internal (baked-in) padding -->
+    <integer name="config_allAppsButtonPaddingPercent">17</integer>
 
     <integer name="config_workspaceDefaultScreen">0</integer>
 
@@ -69,7 +79,9 @@
     <integer name="config_dropAnimMaxDuration">500</integer>
 
     <!-- The duration of the UserFolder opening and closing animation -->
-    <integer name="config_folderAnimDuration">120</integer>
+    <integer name="config_folderExpandDuration">120</integer>
+    <integer name="config_materialFolderExpandDuration">200</integer>
+    <integer name="config_materialFolderExpandStagger">60</integer>
 
     <!-- The distance at which the animation should take the max duration -->
     <integer name="config_dropAnimMaxDist">800</integer>
@@ -81,9 +93,6 @@
     <!-- Camera distance for the overscroll effect -->
     <integer name="config_cameraDistance">8000</integer>
 
-    <!-- Whether or not to use custom clings if a custom workspace layout is passed in -->
-    <bool name="config_useCustomClings">false</bool>
-
 <!-- Hotseat -->
     <bool name="hotseat_transpose_layout_with_orientation">true</bool>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 28b6a5b..2c9e689 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -18,31 +18,23 @@
 <!-- Dynamic Grid -->
     <dimen name="dynamic_grid_edge_margin">6dp</dimen>
     <dimen name="dynamic_grid_search_bar_max_width">500dp</dimen>
-    <dimen name="dynamic_grid_search_bar_height">48dp</dimen>
-    <dimen name="dynamic_grid_page_indicator_height">24dp</dimen>
+    <dimen name="dynamic_grid_search_bar_height">56dp</dimen>
+    <dimen name="dynamic_grid_page_indicator_height">20dp</dimen>
     <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
     <dimen name="dynamic_grid_all_apps_cell_padding">18dp</dimen>
     <dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
     <dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen>
     <dimen name="dynamic_grid_overview_max_icon_zone_height">120dp</dimen>
-    <dimen name="dynamic_grid_overview_bar_max_width">280dp</dimen>
+    <dimen name="dynamic_grid_overview_bar_item_width">48dp</dimen>
+    <dimen name="dynamic_grid_overview_bar_spacer_width">68dp</dimen>
 
 <!-- Cling -->
-    <dimen name="clingPunchThroughGraphicCenterRadius">94dp</dimen>
-    <dimen name="folderClingMarginTop">20dp</dimen>
-    <!-- The offset for the text in the cling -->
-    <dimen name="cling_text_block_offset_x">0dp</dimen>
-    <dimen name="cling_text_block_offset_y">0dp</dimen>
-    <!-- entries for custom clings, will be set in overlays -->
-    <add-resource type="dimen" name="custom_cling_margin_top" />
-    <add-resource type="dimen" name="custom_cling_margin_right" />
-    <add-resource type="dimen" name="custom_cling_margin_left" />
-    
-    <dimen name="cling_title_text_size">20sp</dimen>
-    <dimen name="cling_text_size">14sp</dimen>
-    <dimen name="cling_alt_title_text_size">24sp</dimen>
-    <dimen name="cling_alt_text_size">16sp</dimen>
-    <dimen name="cling_hint_text_size">14sp</dimen>
+    <dimen name="cling_migration_logo_height">240dp</dimen>
+    <dimen name="cling_migration_logo_width">165dp</dimen>
+    <dimen name="cling_migration_bg_size">400dp</dimen>
+    <dimen name="cling_migration_bg_shift">-200dp</dimen>
+    <dimen name="cling_migration_content_margin">16dp</dimen>
+    <dimen name="cling_migration_content_width">280dp</dimen>
 
 <!-- Workspace -->
     <dimen name="workspace_max_gap">16dp</dimen>
@@ -61,6 +53,7 @@
     <dimen name="apps_customize_tab_bar_height">52dp</dimen>
     <dimen name="apps_customize_tab_bar_margin_top">0dp</dimen>
     <dimen name="app_icon_size">48dp</dimen>
+    <dimen name="apps_customize_horizontal_padding">0dp</dimen>
 
     <!-- The AppsCustomize page indicator -->
     <dimen name="apps_customize_page_indicator_height">12dp</dimen>
@@ -87,9 +80,8 @@
     <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>
+    <dimen name="app_widget_preview_label_vertical_padding">8dp</dimen>
+    <dimen name="app_widget_preview_label_horizontal_padding">8dp</dimen>
 
     <!-- Padding applied to shortcut previews -->
     <dimen name="shortcut_preview_padding_left">0dp</dimen>
@@ -100,4 +92,8 @@
     <!-- The amount that the preview contents are inset from the preview background -->
     <dimen name="folder_preview_padding">4dp</dimen>
     <dimen name="folder_name_padding">10dp</dimen>
+
+<!-- Sizes for managed profile badges -->
+    <dimen name="profile_badge_size">24dp</dimen>
+    <dimen name="profile_badge_margin">4dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 66bd36f..ff3509b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -20,6 +20,16 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- General -->
     <skip />
+
+    <!-- URI used to import old favorites. [DO NOT TRANSLATE] -->
+    <string name="old_launcher_provider_uri" translatable="false">content://com.android.launcher2.settings/favorites?notify=true</string>
+
+    <!-- Permission to receive the com.android.launcher3.action.LAUNCH intent -->
+    <string name="receive_launch_broadcasts_permission" translatable="false">com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS</string>
+
+    <!-- Permission to receive the com.android.launcher3.action.FIRST_LOAD_COMPLETE intent -->
+    <string name="receive_first_load_broadcast_permission" translatable="false">com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST</string>
+
     <!-- Application name -->
     <string name="application_name">Launcher3</string>
     <!-- Accessibility-facing application name -->
@@ -30,6 +40,8 @@
     <string name="folder_name"></string>
     <!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
     <string name="activity_not_found">App isn\'t installed.</string>
+    <!-- SafeMode shortcut error string -->
+    <string name="safemode_shortcut_error">Downloaded app disabled in Safe mode</string>
     <!--  Labels for the tabs in the customize drawer -->
     <string name="widgets_tab_label">Widgets</string>
 
@@ -85,9 +97,9 @@
     <!-- Error message when user has filled a home screen -->
     <string name="out_of_space">No more room on this Home screen.</string>
     <!-- Error message when user has filled the hotseat -->
-    <string name="hotseat_out_of_space">No more room on the hotseat.</string>
+    <string name="hotseat_out_of_space">No more room in the Favorites tray</string>
     <!-- Error message when user tries to drop an invalid item on the hotseat -->
-    <string name="invalid_hotseat_item">This widget is too large for the hotseat.</string>
+    <string name="invalid_hotseat_item">This widget is too large for the Favorites tray</string>
     <!-- Message displayed when a shortcut is created by an external application -->
     <string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string>
     <!-- Message displayed when a shortcut is uninstalled by an external application -->
@@ -181,6 +193,9 @@
     <!-- Text to show user in place of a gadget when we can't display it properly -->
     <string name="gadget_error_text">Problem loading widget</string>
 
+    <!-- Text to show user in place of a gadget when it is not yet initialized. -->
+    <string name="gadget_setup_text">Setup</string>
+
     <!-- Text to inform the user that they can't uninstall a system application -->
     <string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
 
@@ -228,6 +243,12 @@
     <string name="workspace_cling_title">Organize your space</string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
     <string name="workspace_cling_move_item">Touch &amp; hold background to manage wallpaper, widgets and settings.</string>
+    <!-- The title text for workspace longpress action [CHAR_LIMIT=40] -->
+    <string name="workspace_cling_longpress_title">Wallpapers, widgets, &amp; settings</string>
+    <!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
+    <string name="workspace_cling_longpress_description">Touch &amp; hold background to customize</string>
+    <!-- The description of the button to dismiss the cling [CHAR_LIMIT=30] -->
+    <string name="workspace_cling_longpress_dismiss">GOT IT</string>
     <!-- The title text for the Folder cling [CHAR_LIMIT=30] -->
     <string name="folder_cling_title">Here\'s a folder</string>
     <!-- The description of how to create a folder [CHAR_LIMIT=70] -->
@@ -252,18 +273,6 @@
     <!-- 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>
-
     <!-- Debug-only activity name. [DO NOT TRANSLATE] -->
     <string name="debug_memory_activity">* HPROF</string>
 
@@ -274,4 +283,29 @@
     <string name="wallpaper_button_text">Wallpapers</string>
     <!-- Text for settings button -->
     <string name="settings_button_text">Settings</string>
+
+    <!-- Label on an icon that references an uninstalled package, that is going to be installed at some point. [CHAR_LIMIT=15] -->
+    <string name="package_state_enqueued">Waiting</string>
+    <!-- Label on an icon that references an uninstalled package, that is currently being downloaded. [CHAR_LIMIT=15] -->
+    <string name="package_state_downloading">Downloading</string>
+    <!-- Label on an icon that references an uninstalled package, that is currently being installed. [CHAR_LIMIT=15] -->
+    <string name="package_state_installing">Installing</string>
+    <!-- Label on an icon that references an uninstalled package, for which we have no information about when it might be installed. [CHAR_LIMIT=15] -->
+    <string name="package_state_unknown">Unknown</string>
+    <!-- Label on an icon that references an uninstalled package, for which restore from market has failed. [CHAR_LIMIT=15] -->
+    <string name="package_state_error">Not restored</string>
+
+    <!-- Button for abandoned promises dialog, that removes all abandoned promise icons. -->
+    <string name="abandoned_clean_all">Remove All</string>
+    <!-- Button for abandoned promises dialog, to removes this abandoned promise icon. -->
+    <string name="abandoned_clean_this">Remove</string>
+    <!-- Button for abandoned promise dialog, to search in the market for the missing package. -->
+    <string name="abandoned_search">Search</string>
+    <!-- Title for abandoned promise dialog. -->
+    <string name="abandoned_promises_title">This app is not installed</string>
+    <!-- Explanation for abandoned promise dialog. "The first 'it' refers to the shortcut icon.
+    The second "it" refers to the app. -->
+    <string name="abandoned_promise_explanation">The app for this icon isn\'t installed.
+        You can remove it, or search for the app and install it manually.
+    </string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c9834f8..56a205f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,53 +18,6 @@
 -->
 
 <resources>
-    <style name="ClingButton">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:paddingTop">15dp</item>
-        <item name="android:paddingBottom">15dp</item>
-        <item name="android:paddingLeft">50dp</item>
-        <item name="android:paddingRight">50dp</item>
-        <item name="android:text">@string/cling_dismiss</item>
-        <item name="android:textColor">#ffffff</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:textSize">16sp</item>
-        <item name="android:background">@drawable/cling_button_bg</item>
-    </style>
-    <style name="ClingTitleText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_marginBottom">5dp</item>
-        <item name="android:textSize">@dimen/cling_title_text_size</item>
-        <item name="android:textColor">#ffffff</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
-    </style>
-    <style name="ClingText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">@dimen/cling_text_size</item>
-        <item name="android:textColor">#80000000</item>
-        <item name="android:lineSpacingMultiplier">1.1</item>
-    </style>
-    <style name="ClingAltTitleText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">@dimen/cling_alt_title_text_size</item>
-        <item name="android:textColor">#49C0EC</item>
-    </style>
-    <style name="ClingAltText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">@dimen/cling_alt_text_size</item>
-        <item name="android:textColor">#49C0EC</item>
-    </style>
-    <style name="ClingHintText">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">@dimen/cling_hint_text_size</item>
-        <item name="android:textColor">#80ffffff</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
-    </style>
 
     <style name="WorkspaceIcon">
         <item name="android:layout_width">match_parent</item>
@@ -86,15 +39,19 @@
 
     <style name="WorkspaceIcon.AppsCustomize">
         <item name="android:background">@null</item>
-        <item name="android:textColor">@color/apps_customize_icon_text_color</item>
+        <item name="android:textColor">@color/quantum_panel_text_color</item>
         <item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item>
-        <item name="android:shadowRadius">4.0</item>
-        <item name="android:shadowColor">#FF000000</item>
+        <item name="android:shadowRadius">0</item>
+        <item name="customShadows">false</item>
     </style>
 
-    <style name="QSBBar">
-        <item name="android:orientation">horizontal</item>
+    <style name="WorkspaceIcon.Folder">
+        <item name="android:background">@null</item>
+        <item name="android:textColor">@color/quantum_panel_text_color</item>
+        <item name="android:shadowRadius">0</item>
+        <item name="customShadows">false</item>
     </style>
+
     <style name="SearchDropTargetBar">
     </style>
     <style name="SearchButton">
@@ -150,11 +107,19 @@
         <item name="android:shadowRadius">2.0</item>
     </style>
 
+    <style name="PreloadIcon">
+        <item name="background">@drawable/virtual_preload</item>
+        <item name="indicatorSize">4dp</item>
+        <item name="ringOutset">4dp</item>
+    </style>
+
+    <style name="PreloadIcon.Folder">
+        <item name="background">@drawable/virtual_preload_folder</item>
+        <item name="indicatorSize">4dp</item>
+        <item name="ringOutset">4dp</item>
+    </style>
+
     <!-- Overridden in device overlays -->
-    <style name="CustomClingTitleText">
-    </style>
-    <style name="CustomClingText">
-    </style>
     <style name="PagedViewWidgetImageView">
         <item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item>
     </style>
diff --git a/res/xml-sw720dp/default_workspace.xml b/res/xml-sw720dp/default_workspace.xml
deleted file mode 100644
index 1c1d70e..0000000
--- a/res/xml-sw720dp/default_workspace.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
-    <!-- Far-left screen [0] -->
-
-    <!-- Left screen [1] -->
-    <appwidget
-        launcher:packageName="com.android.settings"
-        launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
-        launcher:screen="1"
-        launcher:x="0"
-        launcher:y="3"
-        launcher:spanX="4"
-        launcher:spanY="1" />
-
-    <!-- Middle screen [2] -->
-    <appwidget
-        launcher:packageName="com.android.deskclock"
-        launcher:className="com.android.alarmclock.AnalogAppWidgetProvider"
-        launcher:screen="2"
-        launcher:x="1"
-        launcher:y="0"
-        launcher:spanX="2"
-        launcher:spanY="2" />
-    <favorite
-        launcher:packageName="com.android.camera"
-        launcher:className="com.android.camera.Camera"
-        launcher:screen="2"
-        launcher:x="0"
-        launcher:y="3" />
-
-    <!-- Right screen [3] -->
-    <favorite
-        launcher:packageName="com.android.gallery3d"
-        launcher:className="com.android.gallery3d.app.Gallery"
-        launcher:screen="3"
-        launcher:x="1"
-        launcher:y="3" />
-    <favorite
-        launcher:packageName="com.android.settings"
-        launcher:className="com.android.settings.Settings"
-        launcher:screen="3"
-        launcher:x="2"
-        launcher:y="3" />
-
-    <!-- Far-right screen [4] -->
-</favorites>
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace_4x4.xml
similarity index 66%
rename from res/xml/default_workspace.xml
rename to res/xml/default_workspace_4x4.xml
index 26fc504..9bec86a 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace_4x4.xml
@@ -60,13 +60,21 @@
     <!-- Far-right screen [4] -->
 
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <favorite
-        launcher:packageName="com.android.dialer"
-        launcher:className="com.android.dialer.DialtactsActivity"
+    <!-- Dialer, Contacts, [All Apps], Messaging, Browser -->
+    <resolve
         launcher:container="-101"
         launcher:screen="0"
         launcher:x="0"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+
+        <favorite
+            launcher:packageName="com.android.dialer"
+            launcher:className="com.android.dialer.DialtactsActivity" />
+    </resolve>
+
     <favorite
         launcher:packageName="com.android.contacts"
         launcher:className="com.android.contacts.activities.PeopleActivity"
@@ -74,18 +82,35 @@
         launcher:screen="1"
         launcher:x="1"
         launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.mms"
-        launcher:className="com.android.mms.ui.ConversationList"
+
+    <resolve
         launcher:container="-101"
         launcher:screen="3"
         launcher:x="3"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.browser"
-        launcher:className="com.android.browser.BrowserActivity"
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+
+        <favorite
+            launcher:packageName="com.android.mms"
+            launcher:className="com.android.mms.ui.ConversationList" />
+    </resolve>
+    <resolve
         launcher:container="-101"
         launcher:screen="4"
         launcher:x="4"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+
+        <favorite
+            launcher:packageName="com.android.browser"
+            launcher:className="com.android.browser.BrowserActivity" />
+    </resolve>
+
 </favorites>
diff --git a/res/xml/default_workspace_no_all_apps.xml b/res/xml/default_workspace_4x4_no_all_apps.xml
similarity index 100%
rename from res/xml/default_workspace_no_all_apps.xml
rename to res/xml/default_workspace_4x4_no_all_apps.xml
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace_5x5.xml
similarity index 66%
copy from res/xml/default_workspace.xml
copy to res/xml/default_workspace_5x5.xml
index 26fc504..9bec86a 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace_5x5.xml
@@ -60,13 +60,21 @@
     <!-- Far-right screen [4] -->
 
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <favorite
-        launcher:packageName="com.android.dialer"
-        launcher:className="com.android.dialer.DialtactsActivity"
+    <!-- Dialer, Contacts, [All Apps], Messaging, Browser -->
+    <resolve
         launcher:container="-101"
         launcher:screen="0"
         launcher:x="0"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+
+        <favorite
+            launcher:packageName="com.android.dialer"
+            launcher:className="com.android.dialer.DialtactsActivity" />
+    </resolve>
+
     <favorite
         launcher:packageName="com.android.contacts"
         launcher:className="com.android.contacts.activities.PeopleActivity"
@@ -74,18 +82,35 @@
         launcher:screen="1"
         launcher:x="1"
         launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.mms"
-        launcher:className="com.android.mms.ui.ConversationList"
+
+    <resolve
         launcher:container="-101"
         launcher:screen="3"
         launcher:x="3"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.browser"
-        launcher:className="com.android.browser.BrowserActivity"
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+
+        <favorite
+            launcher:packageName="com.android.mms"
+            launcher:className="com.android.mms.ui.ConversationList" />
+    </resolve>
+    <resolve
         launcher:container="-101"
         launcher:screen="4"
         launcher:x="4"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+
+        <favorite
+            launcher:packageName="com.android.browser"
+            launcher:className="com.android.browser.BrowserActivity" />
+    </resolve>
+
 </favorites>
diff --git a/res/xml/default_workspace_5x5_no_all_apps.xml b/res/xml/default_workspace_5x5_no_all_apps.xml
new file mode 100644
index 0000000..f54a204
--- /dev/null
+++ b/res/xml/default_workspace_5x5_no_all_apps.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Dialer Hangouts Maps Chrome Camera -->
+    <favorite
+        launcher:packageName="com.google.android.dialer"
+        launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.talk"
+        launcher:className="com.google.android.talk.SigningInActivity"
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.apps.maps"
+        launcher:className="com.google.android.maps.MapsActivity"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0"/>
+    <favorite
+        launcher:packageName="com.android.chrome"
+        launcher:className="com.google.android.apps.chrome.Main"
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.GoogleCamera"
+        launcher:className="com.android.camera.CameraLauncher"
+        launcher:container="-101"
+        launcher:screen="5"
+        launcher:x="5"
+        launcher:y="0" />
+</favorites>
+
diff --git a/res/xml-sw600dp/default_workspace.xml b/res/xml/default_workspace_5x6.xml
similarity index 65%
rename from res/xml-sw600dp/default_workspace.xml
rename to res/xml/default_workspace_5x6.xml
index 090c7a7..d42a93a 100644
--- a/res/xml-sw600dp/default_workspace.xml
+++ b/res/xml/default_workspace_5x6.xml
@@ -60,13 +60,21 @@
     <!-- Far-right screen [4] -->
 
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <favorite
-        launcher:packageName="com.android.dialer"
-        launcher:className="com.android.dialer.DialtactsActivity"
+    <!-- Dialer, Contacts, [All Apps], Messaging, Browser -->
+    <resolve
         launcher:container="-101"
         launcher:screen="1"
         launcher:x="1"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+
+        <favorite
+            launcher:packageName="com.android.dialer"
+            launcher:className="com.android.dialer.DialtactsActivity" />
+    </resolve>
+
     <favorite
         launcher:packageName="com.android.contacts"
         launcher:className="com.android.contacts.activities.PeopleActivity"
@@ -74,18 +82,34 @@
         launcher:screen="2"
         launcher:x="2"
         launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.mms"
-        launcher:className="com.android.mms.ui.ConversationList"
+
+    <resolve
         launcher:container="-101"
         launcher:screen="4"
         launcher:x="4"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.android.browser"
-        launcher:className="com.android.browser.BrowserActivity"
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+
+        <favorite
+            launcher:packageName="com.android.mms"
+            launcher:className="com.android.mms.ui.ConversationList" />
+    </resolve>
+    <resolve
         launcher:container="-101"
         launcher:screen="5"
         launcher:x="5"
-        launcher:y="0" />
+        launcher:y="0" >
+        <favorite
+            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+
+        <favorite
+            launcher:packageName="com.android.browser"
+            launcher:className="com.android.browser.BrowserActivity" />
+    </resolve>
 </favorites>
diff --git a/res/xml/default_workspace_5x6_no_all_apps.xml b/res/xml/default_workspace_5x6_no_all_apps.xml
new file mode 100644
index 0000000..f54a204
--- /dev/null
+++ b/res/xml/default_workspace_5x6_no_all_apps.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Dialer Hangouts Maps Chrome Camera -->
+    <favorite
+        launcher:packageName="com.google.android.dialer"
+        launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.talk"
+        launcher:className="com.google.android.talk.SigningInActivity"
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.apps.maps"
+        launcher:className="com.google.android.maps.MapsActivity"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0"/>
+    <favorite
+        launcher:packageName="com.android.chrome"
+        launcher:className="com.google.android.apps.chrome.Main"
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.GoogleCamera"
+        launcher:className="com.android.camera.CameraLauncher"
+        launcher:container="-101"
+        launcher:screen="5"
+        launcher:x="5"
+        launcher:y="0" />
+</favorites>
+
diff --git a/src/com/android/launcher3/AddAdapter.java b/src/com/android/launcher3/AddAdapter.java
deleted file mode 100644
index 5308a3d..0000000
--- a/src/com/android/launcher3/AddAdapter.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-/**
- * Adapter showing the types of items that can be added to a {@link Workspace}.
- */
-public class AddAdapter extends BaseAdapter {
-
-    private final LayoutInflater mInflater;
-
-    private final ArrayList<ListItem> mItems = new ArrayList<ListItem>();
-
-    public static final int ITEM_SHORTCUT = 0;
-    public static final int ITEM_APPWIDGET = 1;
-    public static final int ITEM_APPLICATION = 2;
-    public static final int ITEM_WALLPAPER = 3;
-
-    /**
-     * Specific item in our list.
-     */
-    public class ListItem {
-        public final CharSequence text;
-        public final Drawable image;
-        public final int actionTag;
-
-        public ListItem(Resources res, int textResourceId, int imageResourceId, int actionTag) {
-            text = res.getString(textResourceId);
-            if (imageResourceId != -1) {
-                image = res.getDrawable(imageResourceId);
-            } else {
-                image = null;
-            }
-            this.actionTag = actionTag;
-        }
-    }
-    
-    public AddAdapter(Launcher launcher) {
-        super();
-
-        mInflater = (LayoutInflater) launcher.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-        // Create default actions
-        Resources res = launcher.getResources();
-
-        mItems.add(new ListItem(res, R.string.group_wallpapers,
-                R.mipmap.ic_launcher_wallpaper, ITEM_WALLPAPER));
-    }
-
-    public View getView(int position, View convertView, ViewGroup parent) {
-        ListItem item = (ListItem) getItem(position);
-
-        if (convertView == null) {
-            convertView = mInflater.inflate(R.layout.add_list_item, parent, false);
-        }
-
-        TextView textView = (TextView) convertView;
-        textView.setTag(item);
-        textView.setText(item.text);
-        textView.setCompoundDrawablesWithIntrinsicBounds(item.image, null, null, null);
-
-        return convertView;
-    }
-
-    public int getCount() {
-        return mItems.size();
-    }
-
-    public Object getItem(int position) {
-        return mItems.get(position);
-    }
-
-    public long getItemId(int position) {
-        return position;
-    }
-}
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index b641eb5..38d2fa5 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -23,6 +23,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -32,7 +36,7 @@
  */
 class AllAppsList {
     public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
-    
+
     /** The list off all apps. */
     public ArrayList<AppInfo> data =
             new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER);
@@ -66,7 +70,7 @@
         if (mAppFilter != null && !mAppFilter.shouldShowApp(info.componentName)) {
             return;
         }
-        if (findActivity(data, info.componentName)) {
+        if (findActivity(data, info.componentName, info.user)) {
             return;
         }
         data.add(info);
@@ -92,12 +96,14 @@
     /**
      * Add the icons for the supplied apk called packageName.
      */
-    public void addPackage(Context context, String packageName) {
-        final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
+    public void addPackage(Context context, String packageName, UserHandleCompat user) {
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        final List<LauncherActivityInfoCompat> matches = launcherApps.getActivityList(packageName,
+                user);
 
         if (matches.size() > 0) {
-            for (ResolveInfo info : matches) {
-                add(new AppInfo(context.getPackageManager(), info, mIconCache, null));
+            for (LauncherActivityInfoCompat info : matches) {
+                add(new AppInfo(context, info, user, mIconCache, null));
             }
         }
     }
@@ -105,35 +111,37 @@
     /**
      * Remove the apps for the given apk identified by packageName.
      */
-    public void removePackage(String packageName) {
+    public void removePackage(String packageName, UserHandleCompat user) {
         final List<AppInfo> data = this.data;
         for (int i = data.size() - 1; i >= 0; i--) {
             AppInfo info = data.get(i);
             final ComponentName component = info.intent.getComponent();
-            if (packageName.equals(component.getPackageName())) {
+            if (info.user.equals(user) && packageName.equals(component.getPackageName())) {
                 removed.add(info);
                 data.remove(i);
             }
         }
-        // This is more aggressive than it needs to be.
-        mIconCache.flush();
+        mIconCache.remove(packageName, user);
     }
 
     /**
      * Add and remove icons for this package which has been updated.
      */
-    public void updatePackage(Context context, String packageName) {
-        final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
+    public void updatePackage(Context context, String packageName, UserHandleCompat user) {
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        final List<LauncherActivityInfoCompat> matches = launcherApps.getActivityList(packageName,
+                user);
         if (matches.size() > 0) {
             // Find disabled/removed activities and remove them from data and add them
             // to the removed list.
             for (int i = data.size() - 1; i >= 0; i--) {
                 final AppInfo applicationInfo = data.get(i);
                 final ComponentName component = applicationInfo.intent.getComponent();
-                if (packageName.equals(component.getPackageName())) {
+                if (user.equals(applicationInfo.user)
+                        && packageName.equals(component.getPackageName())) {
                     if (!findActivity(matches, component)) {
                         removed.add(applicationInfo);
-                        mIconCache.remove(component);
+                        mIconCache.remove(component, user);
                         data.remove(i);
                     }
                 }
@@ -143,14 +151,14 @@
             // Also updates existing activities with new labels/icons
             int count = matches.size();
             for (int i = 0; i < count; i++) {
-                final ResolveInfo info = matches.get(i);
+                final LauncherActivityInfoCompat info = matches.get(i);
                 AppInfo applicationInfo = findApplicationInfoLocked(
-                        info.activityInfo.applicationInfo.packageName,
-                        info.activityInfo.name);
+                        info.getComponentName().getPackageName(), user,
+                        info.getComponentName().getClassName());
                 if (applicationInfo == null) {
-                    add(new AppInfo(context.getPackageManager(), info, mIconCache, null));
+                    add(new AppInfo(context, info, user, mIconCache, null));
                 } else {
-                    mIconCache.remove(applicationInfo.componentName);
+                    mIconCache.remove(applicationInfo.componentName, user);
                     mIconCache.getTitleAndIcon(applicationInfo, info, null);
                     modified.add(applicationInfo);
                 }
@@ -160,37 +168,24 @@
             for (int i = data.size() - 1; i >= 0; i--) {
                 final AppInfo applicationInfo = data.get(i);
                 final ComponentName component = applicationInfo.intent.getComponent();
-                if (packageName.equals(component.getPackageName())) {
+                if (user.equals(applicationInfo.user)
+                        && packageName.equals(component.getPackageName())) {
                     removed.add(applicationInfo);
-                    mIconCache.remove(component);
+                    mIconCache.remove(component, user);
                     data.remove(i);
                 }
             }
         }
     }
 
-    /**
-     * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
-     */
-    static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
-        final PackageManager packageManager = context.getPackageManager();
-
-        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
-        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-        mainIntent.setPackage(packageName);
-
-        final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
-        return apps != null ? apps : new ArrayList<ResolveInfo>();
-    }
 
     /**
      * Returns whether <em>apps</em> contains <em>component</em>.
      */
-    private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
-        final String className = component.getClassName();
-        for (ResolveInfo info : apps) {
-            final ActivityInfo activityInfo = info.activityInfo;
-            if (activityInfo.name.equals(className)) {
+    private static boolean findActivity(List<LauncherActivityInfoCompat> apps,
+            ComponentName component) {
+        for (LauncherActivityInfoCompat info : apps) {
+            if (info.getComponentName().equals(component)) {
                 return true;
             }
         }
@@ -198,13 +193,24 @@
     }
 
     /**
+     * Query the launcher apps service for whether the supplied package has
+     * MAIN/LAUNCHER activities in the supplied package.
+     */
+    static boolean packageHasActivities(Context context, String packageName,
+            UserHandleCompat user) {
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        return launcherApps.getActivityList(packageName, user).size() > 0;
+    }
+
+    /**
      * Returns whether <em>apps</em> contains <em>component</em>.
      */
-    private static boolean findActivity(ArrayList<AppInfo> apps, ComponentName component) {
+    private static boolean findActivity(ArrayList<AppInfo> apps, ComponentName component,
+            UserHandleCompat user) {
         final int N = apps.size();
-        for (int i=0; i<N; i++) {
+        for (int i = 0; i < N; i++) {
             final AppInfo info = apps.get(i);
-            if (info.componentName.equals(component)) {
+            if (info.user.equals(user) && info.componentName.equals(component)) {
                 return true;
             }
         }
@@ -214,10 +220,11 @@
     /**
      * Find an ApplicationInfo object for the given packageName and className.
      */
-    private AppInfo findApplicationInfoLocked(String packageName, String className) {
+    private AppInfo findApplicationInfoLocked(String packageName, UserHandleCompat user,
+            String className) {
         for (AppInfo info: data) {
             final ComponentName component = info.intent.getComponent();
-            if (packageName.equals(component.getPackageName())
+            if (user.equals(info.user) && packageName.equals(component.getPackageName())
                     && className.equals(component.getClassName())) {
                 return info;
             }
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index d5a7769..bfcad84 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -17,21 +17,26 @@
 package com.android.launcher3;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
 import android.util.Log;
 
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 
 /**
  * Represents an app in AllAppsView.
  */
-class AppInfo extends ItemInfo {
+public class AppInfo extends ItemInfo {
     private static final String TAG = "Launcher3.AppInfo";
 
     /**
@@ -60,35 +65,36 @@
         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
     }
 
-    protected Intent getIntent() {
+    public Intent getIntent() {
         return intent;
     }
 
+    protected Intent getRestoredIntent() {
+        return null;
+    }
+
     /**
      * Must not hold the Context.
      */
-    public AppInfo(PackageManager pm, ResolveInfo info, IconCache iconCache,
-            HashMap<Object, CharSequence> labelCache) {
-        final String packageName = info.activityInfo.applicationInfo.packageName;
-
-        this.componentName = new ComponentName(packageName, info.activityInfo.name);
+    public AppInfo(Context context, LauncherActivityInfoCompat info, UserHandleCompat user,
+            IconCache iconCache, HashMap<Object, CharSequence> labelCache) {
+        this.componentName = info.getComponentName();
         this.container = ItemInfo.NO_ID;
-        this.setActivity(componentName,
-                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
-        try {
-            PackageInfo pi = pm.getPackageInfo(packageName, 0);
-            flags = initFlags(pi);
-            firstInstallTime = initFirstInstallTime(pi);
-        } catch (NameNotFoundException e) {
-            Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
-        }
-
+        flags = initFlags(info);
+        firstInstallTime = info.getFirstInstallTime();
         iconCache.getTitleAndIcon(this, info, labelCache);
+        intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setComponent(info.getComponentName());
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
+        intent.putExtra(EXTRA_PROFILE, serialNumber);
+        this.user = user;
     }
 
-    public static int initFlags(PackageInfo pi) {
-        int appFlags = pi.applicationInfo.flags;
+    private static int initFlags(LauncherActivityInfoCompat info) {
+        int appFlags = info.getApplicationInfo().flags;
         int flags = 0;
         if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
             flags |= DOWNLOADED_FLAG;
@@ -100,10 +106,6 @@
         return flags;
     }
 
-    public static long initFirstInstallTime(PackageInfo pi) {
-        return pi.firstInstallTime;
-    }
-
     public AppInfo(AppInfo info) {
         super(info);
         componentName = info.componentName;
@@ -111,21 +113,7 @@
         intent = new Intent(info.intent);
         flags = info.flags;
         firstInstallTime = info.firstInstallTime;
-    }
-
-    /**
-     * Creates the application intent based on a component name and various launch flags.
-     * Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
-     *
-     * @param className the class name of the component representing the intent
-     * @param launchFlags the launch flags
-     */
-    final void setActivity(ComponentName className, int launchFlags) {
-        intent = new Intent(Intent.ACTION_MAIN);
-        intent.addCategory(Intent.CATEGORY_LAUNCHER);
-        intent.setComponent(className);
-        intent.setFlags(launchFlags);
-        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
+        iconBitmap = info.iconBitmap;
     }
 
     @Override
@@ -133,7 +121,8 @@
         return "ApplicationInfo(title=" + title.toString() + " id=" + this.id
                 + " type=" + this.itemType + " container=" + this.container
                 + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY
-                + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + dropPos + ")";
+                + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
+                + " user=" + user + ")";
     }
 
     public static void dumpApplicationInfoList(String tag, String label, ArrayList<AppInfo> list) {
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
new file mode 100644
index 0000000..880aaf1
--- /dev/null
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -0,0 +1,94 @@
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "AppWidgetsRestoredReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) {
+            int[] oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
+            int[] newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
+            if (oldIds.length == newIds.length) {
+                restoreAppWidgetIds(context, oldIds, newIds);
+            } else {
+                Log.e(TAG, "Invalid host restored received");
+            }
+        }
+    }
+
+    /**
+     * Updates the app widgets whose id has changed during the restore process.
+     */
+    static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
+        final ContentResolver cr = context.getContentResolver();
+        final List<Integer> idsToRemove = new ArrayList<Integer>();
+        final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
+
+        for (int i = 0; i < oldWidgetIds.length; i++) {
+            Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
+
+            final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
+            final int state;
+            if (LauncherModel.isValidProvider(provider)) {
+                state = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+            } else {
+                state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+            }
+
+            ContentValues values = new ContentValues();
+            values.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]);
+            values.put(LauncherSettings.Favorites.RESTORED, state);
+
+            String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) };
+
+            int result = cr.update(Favorites.CONTENT_URI, values,
+                    "appWidgetId=? and (restored & 1) = 1", widgetIdParams);
+            if (result == 0) {
+                Cursor cursor = cr.query(Favorites.CONTENT_URI,
+                        new String[] {Favorites.APPWIDGET_ID},
+                        "appWidgetId=?", widgetIdParams, null);
+                try {
+                    if (!cursor.moveToFirst()) {
+                        // The widget no long exists.
+                        idsToRemove.add(newWidgetIds[i]);
+                    }
+                } finally {
+                    cursor.close();
+                }
+            }
+        }
+        // Unregister the widget IDs which are not present on the workspace. This could happen
+        // when a widget place holder is removed from workspace, before this method is called.
+        if (!idsToRemove.isEmpty()) {
+            final AppWidgetHost appWidgetHost =
+                    new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
+            new AsyncTask<Void, Void, Void>() {
+                public Void doInBackground(Void ... args) {
+                    for (Integer id : idsToRemove) {
+                        appWidgetHost.deleteAppWidgetId(id);
+                        Log.e(TAG, "Widget no longer present, appWidgetId=" + id);
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/AppsCustomizeCellLayout.java b/src/com/android/launcher3/AppsCustomizeCellLayout.java
index 3c8bda9..a50fb68 100644
--- a/src/com/android/launcher3/AppsCustomizeCellLayout.java
+++ b/src/com/android/launcher3/AppsCustomizeCellLayout.java
@@ -20,8 +20,16 @@
 import android.view.View;
 
 public class AppsCustomizeCellLayout extends CellLayout implements Page {
+
+    final FocusIndicatorView mFocusHandlerView;
+
     public AppsCustomizeCellLayout(Context context) {
         super(context);
+
+        mFocusHandlerView = new FocusIndicatorView(context);
+        addView(mFocusHandlerView, 0);
+        mFocusHandlerView.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
+        mFocusHandlerView.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
     }
 
     @Override
@@ -60,4 +68,4 @@
             children.getChildAt(j).setOnKeyListener(null);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 37cdb9e..1bd2907 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -28,7 +28,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -44,12 +43,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 import android.widget.GridLayout;
 import android.widget.ImageView;
 import android.widget.Toast;
 
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -144,10 +143,11 @@
  */
 public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
         View.OnClickListener, View.OnKeyListener, DragSource,
-        PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
-        LauncherTransitionable {
+        PagedViewWidget.ShortPressListener, LauncherTransitionable {
     static final String TAG = "AppsCustomizePagedView";
 
+    private static Rect sTmpRect = new Rect();
+
     /**
      * The different content types that this paged view can show.
      */
@@ -165,40 +165,22 @@
 
     // Save and Restore
     private int mSaveInstanceStateItemIndex = -1;
-    private PagedViewIcon mPressedIcon;
 
     // Content
     private ArrayList<AppInfo> mApps;
     private ArrayList<Object> mWidgets;
 
-    // Cling
-    private boolean mHasShownAllAppsCling;
-    private int mClingFocusedX;
-    private int mClingFocusedY;
-
     // Caching
-    private Canvas mCanvas;
     private IconCache mIconCache;
 
     // Dimens
     private int mContentWidth, mContentHeight;
     private int mWidgetCountX, mWidgetCountY;
-    private int mWidgetWidthGap, mWidgetHeightGap;
     private PagedViewCellLayout mWidgetSpacingLayout;
     private int mNumAppsPages;
     private int mNumWidgetPages;
     private Rect mAllAppsPadding = new Rect();
 
-    // Relating to the scroll and overscroll effects
-    Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
-    private static float CAMERA_DISTANCE = 6500;
-    private static float TRANSITION_SCALE_FACTOR = 0.74f;
-    private static float TRANSITION_PIVOT = 0.65f;
-    private static float TRANSITION_MAX_ROTATION = 22;
-    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
-    private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
-    private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
-
     // Previews & outlines
     ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
     private static final int sPageSleepDelay = 200;
@@ -213,6 +195,7 @@
     int mWidgetLoadingId = -1;
     PendingAddWidgetInfo mCreateWidgetInfo = null;
     private boolean mDraggingWidget = false;
+    boolean mPageBackgroundsVisible = true;
 
     private Toast mWidgetInstructionToast;
 
@@ -223,19 +206,6 @@
     private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
         new ArrayList<Runnable>();
 
-    private Rect mTmpRect = new Rect();
-
-    // 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();
-
     WidgetPreviewLoader mWidgetPreviewLoader;
 
     private boolean mInBulkBind;
@@ -248,18 +218,12 @@
         mApps = new ArrayList<AppInfo>();
         mWidgets = new ArrayList<Object>();
         mIconCache = (LauncherAppState.getInstance()).getIconCache();
-        mCanvas = new Canvas();
         mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
 
         // Save the default widget preview background
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mWidgetWidthGap = mWidgetHeightGap = grid.edgeMarginPx;
         mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
         mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
-        mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0);
-        mClingFocusedY = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedY, 0);
         a.recycle();
         mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
 
@@ -271,6 +235,7 @@
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+        setSinglePageInViewport();
     }
 
     @Override
@@ -295,8 +260,16 @@
     void setAllAppsPadding(Rect r) {
         mAllAppsPadding.set(r);
     }
+
     void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) {
-        mPageLayoutPaddingBottom = pageIndicatorHeight;
+        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), pageIndicatorHeight);
+    }
+
+    WidgetPreviewLoader getWidgetPreviewLoader() {
+        if (mWidgetPreviewLoader == null) {
+            mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher);
+        }
+        return mWidgetPreviewLoader;
     }
 
     /** Returns the item index of the center item on this page so that we can restore to this
@@ -364,16 +337,10 @@
     }
 
     protected void onDataReady(int width, int height) {
-        if (mWidgetPreviewLoader == null) {
-            mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher);
-        }
-
         // Now that the data is ready, we can calculate the content width, the number of cells to
         // use for each page
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
-                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
         mCellCountX = (int) grid.allAppsNumCols;
         mCellCountY = (int) grid.allAppsNumRows;
         updatePageCounts();
@@ -385,54 +352,32 @@
         int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
         mWidgetSpacingLayout.measure(widthSpec, heightSpec);
 
-        AppsCustomizeTabHost host = (AppsCustomizeTabHost) getTabHost();
-        final boolean hostIsTransitioning = host.isTransitioning();
-
-        // Restore the page
+        final boolean hostIsTransitioning = getTabHost().isInTransition();
         int page = getPageForComponent(mSaveInstanceStateItemIndex);
         invalidatePageData(Math.max(0, page), hostIsTransitioning);
-
-        // Show All Apps cling if we are finished transitioning, otherwise, we will try again when
-        // the transition completes in AppsCustomizeTabHost (otherwise the wrong offsets will be
-        // returned while animating)
-        if (!hostIsTransitioning) {
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    showAllAppsCling();
-                }
-            });
-        }
     }
 
-    void showAllAppsCling() {
-        if (!mHasShownAllAppsCling && isDataReady()) {
-            mHasShownAllAppsCling = true;
-            // Calculate the position for the cling punch through
-            int[] offset = new int[2];
-            int[] pos = mWidgetSpacingLayout.estimateCellPosition(mClingFocusedX, mClingFocusedY);
-            mLauncher.getDragLayer().getLocationInDragLayer(this, offset);
-            // PagedViews are centered horizontally but top aligned
-            // Note we have to shift the items up now that Launcher sits under the status bar
-            pos[0] += (getMeasuredWidth() - mWidgetSpacingLayout.getMeasuredWidth()) / 2 +
-                    offset[0];
-            pos[1] += offset[1] - mLauncher.getDragLayer().getPaddingTop();
-        }
-    }
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
 
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        int height = MeasureSpec.getSize(heightMeasureSpec);
         if (!isDataReady()) {
             if ((LauncherAppState.isDisableAllApps() || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
-                setDataIsReady();
-                setMeasuredDimension(width, height);
-                onDataReady(width, height);
+                post(new Runnable() {
+                    // This code triggers requestLayout so must be posted outside of the
+                    // layout pass.
+                    public void run() {
+                        boolean attached = true;
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                            attached = isAttachedToWindow();
+                        }
+                        if (attached) {
+                            setDataIsReady();
+                            onDataReady(getMeasuredWidth(), getMeasuredHeight());
+                        }
+                    }
+                });
             }
         }
-
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
     public void onPackagesUpdated(ArrayList<Object> widgetsAndShortcuts) {
@@ -447,7 +392,6 @@
                 if (!app.shouldShowAppOrWidgetProvider(widget.provider)) {
                     continue;
                 }
-                widget.label = widget.label.trim();
                 if (widget.minWidth > 0 && widget.minHeight > 0) {
                     // Ensure that all widgets we show can be added on a workspace of this size
                     int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
@@ -497,40 +441,29 @@
     @Override
     public void onClick(View v) {
         // When we have exited all apps or are in transition, disregard clicks
-        if (!mLauncher.isAllAppsVisible() ||
-                mLauncher.getWorkspace().isSwitchingState()) return;
+        if (!mLauncher.isAllAppsVisible()
+                || mLauncher.getWorkspace().isSwitchingState()
+                || !(v instanceof PagedViewWidget)) return;
 
-        if (v instanceof PagedViewIcon) {
-            // Animate some feedback to the click
-            final AppInfo appInfo = (AppInfo) v.getTag();
-
-            // Lock the drawable state to pressed until we return to Launcher
-            if (mPressedIcon != null) {
-                mPressedIcon.lockDrawableState();
-            }
-            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
-            mLauncher.getStats().recordLaunch(appInfo.intent);
-        } else if (v instanceof PagedViewWidget) {
-            // Let the user know that they have to long press to add a widget
-            if (mWidgetInstructionToast != null) {
-                mWidgetInstructionToast.cancel();
-            }
-            mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
-                Toast.LENGTH_SHORT);
-            mWidgetInstructionToast.show();
-
-            // Create a little animation to show that the widget can move
-            float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
-            final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
-            AnimatorSet bounce = LauncherAnimUtils.createAnimatorSet();
-            ValueAnimator tyuAnim = LauncherAnimUtils.ofFloat(p, "translationY", offsetY);
-            tyuAnim.setDuration(125);
-            ValueAnimator tydAnim = LauncherAnimUtils.ofFloat(p, "translationY", 0f);
-            tydAnim.setDuration(100);
-            bounce.play(tyuAnim).before(tydAnim);
-            bounce.setInterpolator(new AccelerateInterpolator());
-            bounce.start();
+        // Let the user know that they have to long press to add a widget
+        if (mWidgetInstructionToast != null) {
+            mWidgetInstructionToast.cancel();
         }
+        mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
+            Toast.LENGTH_SHORT);
+        mWidgetInstructionToast.show();
+
+        // Create a little animation to show that the widget can move
+        float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+        final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
+        AnimatorSet bounce = LauncherAnimUtils.createAnimatorSet();
+        ValueAnimator tyuAnim = LauncherAnimUtils.ofFloat(p, "translationY", offsetY);
+        tyuAnim.setDuration(125);
+        ValueAnimator tydAnim = LauncherAnimUtils.ofFloat(p, "translationY", 0f);
+        tydAnim.setDuration(100);
+        bounce.play(tyuAnim).before(tydAnim);
+        bounce.setInterpolator(new AccelerateInterpolator());
+        bounce.start();
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -546,30 +479,29 @@
     }
 
     private void beginDraggingApplication(View v) {
-        mLauncher.getWorkspace().onDragStartedWithItem(v);
         mLauncher.getWorkspace().beginDragShared(v, this);
     }
 
-    Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
+    static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
         Bundle options = null;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, mTmpRect);
-            Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(mLauncher,
+            AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, sTmpRect);
+            Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher,
                     info.componentName, null);
 
-            float density = getResources().getDisplayMetrics().density;
+            float density = launcher.getResources().getDisplayMetrics().density;
             int xPaddingDips = (int) ((padding.left + padding.right) / density);
             int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
 
             options = new Bundle();
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
-                    mTmpRect.left - xPaddingDips);
+                    sTmpRect.left - xPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
-                    mTmpRect.top - yPaddingDips);
+                    sTmpRect.top - yPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
-                    mTmpRect.right - xPaddingDips);
+                    sTmpRect.right - xPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
-                    mTmpRect.bottom - yPaddingDips);
+                    sTmpRect.bottom - yPaddingDips);
         }
         return options;
     }
@@ -588,18 +520,9 @@
             @Override
             public void run() {
                 mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
-                // Options will be null for platforms with JB or lower, so this serves as an
-                // SDK level check.
-                if (options == null) {
-                    if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
-                            mWidgetLoadingId, info.componentName)) {
-                        mWidgetCleanupState = WIDGET_BOUND;
-                    }
-                } else {
-                    if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
-                            mWidgetLoadingId, info.componentName, options)) {
-                        mWidgetCleanupState = WIDGET_BOUND;
-                    }
+                if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
+                        mWidgetLoadingId, pInfo, options)) {
+                    mWidgetCleanupState = WIDGET_BOUND;
                 }
             }
         };
@@ -727,13 +650,12 @@
 
             int[] previewSizeBeforeScale = new int[1];
 
-            preview = mWidgetPreviewLoader.generateWidgetPreview(createWidgetInfo.componentName,
-                    createWidgetInfo.previewImage, createWidgetInfo.icon, spanX, spanY,
-                    maxWidth, maxHeight, null, previewSizeBeforeScale);
+            preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.info,
+                    spanX, spanY, maxWidth, maxHeight, null, previewSizeBeforeScale);
 
             // Compare the size of the drag preview to the preview in the AppsCustomize tray
             int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0],
-                    mWidgetPreviewLoader.maxWidthForWidgetPreview(spanX));
+                    getWidgetPreviewLoader().maxWidthForWidgetPreview(spanX));
             scale = previewWidthInAppsCustomize / (float) preview.getWidth();
 
             // The bitmap in the AppsCustomize tray is always the the same size, so there
@@ -746,15 +668,7 @@
         } else {
             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();
-            WidgetPreviewLoader.renderDrawableToBitmap(icon, preview, 0, 0,
-                    icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
-            mCanvas.restore();
-            mCanvas.setBitmap(null);
+            preview = Utilities.createIconBitmap(icon, mLauncher);
             createItemInfo.spanX = createItemInfo.spanY = 1;
         }
 
@@ -780,7 +694,7 @@
     protected boolean beginDragging(final View v) {
         if (!super.beginDragging(v)) return false;
 
-        if (v instanceof PagedViewIcon) {
+        if (v instanceof BubbleTextView) {
             beginDraggingApplication(v);
         } else if (v instanceof PagedViewWidget) {
             if (!beginDraggingWidget(v)) {
@@ -795,9 +709,6 @@
             public void run() {
                 // We don't enter spring-loaded mode if the drag has been cancelled
                 if (mLauncher.getDragController().isDragging()) {
-                    // Reset the alpha on the dragged icon before we drag
-                    resetDrawableState();
-
                     // Go into spring loaded mode (must happen before we startDrag())
                     mLauncher.enterSpringLoadedDragMode();
                 }
@@ -814,16 +725,11 @@
      */
     private void endDragging(View target, boolean isFlingToDelete, boolean success) {
         if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
-                !(target instanceof DeleteDropTarget))) {
+                !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
             // Exit spring loaded mode if we have not successfully dropped or have not handled the
             // drop in Workspace
-            mLauncher.getWorkspace().removeExtraEmptyScreen(true, new Runnable() {
-                @Override
-                public void run() {
-                    mLauncher.exitSpringLoadedDragMode();
-                    mLauncher.unlockScreenOrientation(false);
-                }
-            });
+            mLauncher.exitSpringLoadedDragMode();
+            mLauncher.unlockScreenOrientation(false);
         } else {
             mLauncher.unlockScreenOrientation(false);
         }
@@ -1016,13 +922,28 @@
         setVisibilityOnChildren(layout, View.GONE);
         int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
-        layout.setMinimumWidth(getPageContentWidth());
         layout.measure(widthSpec, heightSpec);
-        layout.setPadding(mAllAppsPadding.left, mAllAppsPadding.top, mAllAppsPadding.right,
-                mAllAppsPadding.bottom);
+
+        Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel);
+        if (bg != null) {
+            bg.setAlpha(mPageBackgroundsVisible ? 255: 0);
+            layout.setBackground(bg);
+        }
+
         setVisibilityOnChildren(layout, View.VISIBLE);
     }
 
+    public void setPageBackgroundsVisible(boolean visible) {
+        mPageBackgroundsVisible = visible;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            Drawable bg = getChildAt(i).getBackground();
+            if (bg != null) {
+                bg.setAlpha(visible ? 255 : 0);
+            }
+        }
+    }
+
     public void syncAppsPageItems(int page, boolean immediate) {
         // ensure that we have the right number of items on the pages
         final boolean isRtl = isLayoutRtl();
@@ -1036,13 +957,14 @@
         ArrayList<Bitmap> images = new ArrayList<Bitmap>();
         for (int i = startIndex; i < endIndex; ++i) {
             AppInfo info = mApps.get(i);
-            PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
+            BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
                     R.layout.apps_customize_application, layout, false);
-            icon.applyFromApplicationInfo(info, true, this);
-            icon.setOnClickListener(this);
+            icon.applyFromApplicationInfo(info);
+            icon.setOnClickListener(mLauncher);
             icon.setOnLongClickListener(this);
             icon.setOnTouchListener(this);
             icon.setOnKeyListener(this);
+            icon.setOnFocusChangeListener(layout.mFocusHandlerView);
 
             int index = i - startIndex;
             int x = index % mCellCountX;
@@ -1147,7 +1069,7 @@
                     // do cleanup inside onSyncWidgetPageItems
                     onSyncWidgetPageItems(data, false);
                 }
-            }, mWidgetPreviewLoader);
+            }, getWidgetPreviewLoader());
 
         // Ensure that the task is appropriately prioritized and runs in parallel
         AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page,
@@ -1165,21 +1087,27 @@
         // immediately after syncing, we don't have a proper width.
         int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
-        layout.setMinimumWidth(getPageContentWidth());
+
+        Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel_dark);
+        if (bg != null) {
+            bg.setAlpha(mPageBackgroundsVisible ? 255 : 0);
+            layout.setBackground(bg);
+        }
         layout.measure(widthSpec, heightSpec);
     }
 
     public void syncWidgetPageItems(final int page, final boolean immediate) {
         int numItemsPerPage = mWidgetCountX * mWidgetCountY;
 
+        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
+
         // Calculate the dimensions of each cell we are giving to each widget
         final ArrayList<Object> items = new ArrayList<Object>();
-        int contentWidth = mContentWidth;
-        final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft - mPageLayoutPaddingRight
-                - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
-        int contentHeight = mContentHeight;
-        final int cellHeight = ((contentHeight - mPageLayoutPaddingTop - mPageLayoutPaddingBottom
-                - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);
+        int contentWidth = mContentWidth - layout.getPaddingLeft() - layout.getPaddingRight();
+        final int cellWidth = contentWidth / mWidgetCountX;
+        int contentHeight = mContentHeight - layout.getPaddingTop() - layout.getPaddingBottom();
+
+        final int cellHeight = contentHeight / mWidgetCountY;
 
         // Prepare the set of widgets to load previews for in the background
         int offset = page * numItemsPerPage;
@@ -1188,7 +1116,6 @@
         }
 
         // Prepopulate the pages with the other widget info, and fill in the previews later
-        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
         layout.setColumnCount(layout.getCellCountX());
         for (int i = 0; i < items.size(); ++i) {
             Object rawInfo = items.get(i);
@@ -1208,7 +1135,7 @@
                 createItemInfo.minSpanX = minSpanXY[0];
                 createItemInfo.minSpanY = minSpanXY[1];
 
-                widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, mWidgetPreviewLoader);
+                widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, getWidgetPreviewLoader());
                 widget.setTag(createItemInfo);
                 widget.setShortPressListener(this);
             } else if (rawInfo instanceof ResolveInfo) {
@@ -1218,7 +1145,7 @@
                 createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
                 createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
                         info.activityInfo.name);
-                widget.applyFromResolveInfo(mPackageManager, info, mWidgetPreviewLoader);
+                widget.applyFromResolveInfo(mPackageManager, info, getWidgetPreviewLoader());
                 widget.setTag(createItemInfo);
             }
             widget.setOnClickListener(this);
@@ -1229,14 +1156,22 @@
             // Layout each widget
             int ix = i % mWidgetCountX;
             int iy = i / mWidgetCountX;
+
+            if (ix > 0) {
+                View border = widget.findViewById(R.id.left_border);
+                border.setVisibility(View.VISIBLE);
+            }
+            if (ix < mWidgetCountX - 1) {
+                View border = widget.findViewById(R.id.right_border);
+                border.setVisibility(View.VISIBLE);
+            }
+
             GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
                     GridLayout.spec(iy, GridLayout.START),
                     GridLayout.spec(ix, GridLayout.TOP));
             lp.width = cellWidth;
             lp.height = cellHeight;
             lp.setGravity(Gravity.TOP | Gravity.START);
-            if (ix > 0) lp.leftMargin = mWidgetWidthGap;
-            if (iy > 0) lp.topMargin = mWidgetHeightGap;
             layout.addView(widget, lp);
         }
 
@@ -1255,11 +1190,11 @@
                     maxPreviewHeight = maxSize[1];
                 }
 
-                mWidgetPreviewLoader.setPreviewSize(
+                getWidgetPreviewLoader().setPreviewSize(
                         maxPreviewWidth, maxPreviewHeight, mWidgetSpacingLayout);
                 if (immediate) {
                     AsyncTaskPageData data = new AsyncTaskPageData(page, items,
-                            maxPreviewWidth, maxPreviewHeight, null, null, mWidgetPreviewLoader);
+                            maxPreviewWidth, maxPreviewHeight, null, null, getWidgetPreviewLoader());
                     loadWidgetPreviewsInBackground(null, data);
                     onSyncWidgetPageItems(data, immediate);
                 } else {
@@ -1296,7 +1231,7 @@
                 task.syncThreadPriority();
             }
 
-            images.add(mWidgetPreviewLoader.getPreview(items.get(i)));
+            images.add(getWidgetPreviewLoader().getPreview(items.get(i)));
         }
     }
 
@@ -1386,86 +1321,7 @@
     // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
     @Override
     protected void screenScrolled(int screenCenter) {
-        final boolean isRtl = isLayoutRtl();
         super.screenScrolled(screenCenter);
-
-        for (int i = 0; i < getChildCount(); i++) {
-            View v = getPageAt(i);
-            if (v != null) {
-                float scrollProgress = getScrollProgress(screenCenter, v, i);
-
-                float interpolatedProgress;
-                float translationX;
-                float maxScrollProgress = Math.max(0, scrollProgress);
-                float minScrollProgress = Math.min(0, scrollProgress);
-
-                if (isRtl) {
-                    translationX = maxScrollProgress * v.getMeasuredWidth();
-                    interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(maxScrollProgress));
-                } else {
-                    translationX = minScrollProgress * v.getMeasuredWidth();
-                    interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(minScrollProgress));
-                }
-                float scale = (1 - interpolatedProgress) +
-                        interpolatedProgress * TRANSITION_SCALE_FACTOR;
-
-                float alpha;
-                if (isRtl && (scrollProgress > 0)) {
-                    alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(maxScrollProgress));
-                } else if (!isRtl && (scrollProgress < 0)) {
-                    alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(scrollProgress));
-                } else {
-                    //  On large screens we need to fade the page as it nears its leftmost position
-                    alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
-                }
-
-                v.setCameraDistance(mDensity * CAMERA_DISTANCE);
-                int pageWidth = v.getMeasuredWidth();
-                int pageHeight = v.getMeasuredHeight();
-
-                if (PERFORM_OVERSCROLL_ROTATION) {
-                    float xPivot = isRtl ? 1f - TRANSITION_PIVOT : TRANSITION_PIVOT;
-                    boolean isOverscrollingFirstPage = isRtl ? scrollProgress > 0 : scrollProgress < 0;
-                    boolean isOverscrollingLastPage = isRtl ? scrollProgress < 0 : scrollProgress > 0;
-
-                    if (i == 0 && isOverscrollingFirstPage) {
-                        // Overscroll to the left
-                        v.setPivotX(xPivot * pageWidth);
-                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
-                        scale = 1.0f;
-                        alpha = 1.0f;
-                        // On the first page, we don't want the page to have any lateral motion
-                        translationX = 0;
-                    } else if (i == getChildCount() - 1 && isOverscrollingLastPage) {
-                        // Overscroll to the right
-                        v.setPivotX((1 - xPivot) * pageWidth);
-                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
-                        scale = 1.0f;
-                        alpha = 1.0f;
-                        // On the last page, we don't want the page to have any lateral motion.
-                        translationX = 0;
-                    } else {
-                        v.setPivotY(pageHeight / 2.0f);
-                        v.setPivotX(pageWidth / 2.0f);
-                        v.setRotationY(0f);
-                    }
-                }
-
-                v.setTranslationX(translationX);
-                v.setScaleX(scale);
-                v.setScaleY(scale);
-                v.setAlpha(alpha);
-
-                // If the view has 0 alpha, we set it to be invisible so as to prevent
-                // it from accepting touches
-                if (alpha == 0) {
-                    v.setVisibility(INVISIBLE);
-                } else if (v.getVisibility() != VISIBLE) {
-                    v.setVisibility(VISIBLE);
-                }
-            }
-        }
-
         enableHwLayersOnVisiblePages();
     }
 
@@ -1510,7 +1366,7 @@
     }
 
     protected void overScroll(float amount) {
-        acceleratedOverScroll(amount);
+        dampedOverScroll(amount);
     }
 
     /**
@@ -1584,7 +1440,8 @@
         int length = list.size();
         for (int i = 0; i < length; ++i) {
             AppInfo info = list.get(i);
-            if (info.intent.getComponent().equals(removeComponent)) {
+            if (info.user.equals(item.user)
+                    && info.intent.getComponent().equals(removeComponent)) {
                 return i;
             }
         }
@@ -1622,12 +1479,8 @@
         // If we have reset, then we should not continue to restore the previous state
         mSaveInstanceStateItemIndex = -1;
 
-        AppsCustomizeTabHost tabHost = getTabHost();
-        String tag = tabHost.getCurrentTabTag();
-        if (tag != null) {
-            if (!tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
-                tabHost.setCurrentTabFromContent(ContentType.Applications);
-            }
+        if (mContentType != ContentType.Applications) {
+            setContentType(ContentType.Applications);
         }
 
         if (mCurrentPage != 0) {
@@ -1671,23 +1524,6 @@
         cancelAllTasks();
     }
 
-    @Override
-    public void iconPressed(PagedViewIcon icon) {
-        // Reset the previously pressed icon and store a reference to the pressed icon so that
-        // we can reset it on return to Launcher (in Launcher.onResume())
-        if (mPressedIcon != null) {
-            mPressedIcon.resetDrawableState();
-        }
-        mPressedIcon = icon;
-    }
-
-    public void resetDrawableState() {
-        if (mPressedIcon != null) {
-            mPressedIcon.resetDrawableState();
-            mPressedIcon = null;
-        }
-    }
-
     /*
      * We load an extra page on each side to prevent flashes from scrolling and loading of the
      * widget previews in the background with the AsyncTasks.
@@ -1725,4 +1561,4 @@
 
         return String.format(getContext().getString(stringId), page + 1, count);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
index bb7f045..9a516fd 100644
--- a/src/com/android/launcher3/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher3/AppsCustomizeTabHost.java
@@ -29,6 +29,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TabHost;
@@ -37,35 +38,20 @@
 
 import java.util.ArrayList;
 
-public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
-        TabHost.OnTabChangeListener, Insettable  {
+public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransitionable, Insettable  {
     static final String LOG_TAG = "AppsCustomizeTabHost";
 
     private static final String APPS_TAB_TAG = "APPS";
     private static final String WIDGETS_TAB_TAG = "WIDGETS";
 
-    private final LayoutInflater mLayoutInflater;
-    private ViewGroup mTabs;
-    private ViewGroup mTabsContainer;
-    private AppsCustomizePagedView mAppsCustomizePane;
-    private FrameLayout mAnimationBuffer;
-    private LinearLayout mContent;
+    private AppsCustomizePagedView mPagedView;
+    private View mContent;
+    private boolean mInTransition = false;
 
-    private boolean mInTransition;
-    private boolean mTransitioningToWorkspace;
-    private boolean mResetAfterTransition;
-    private Runnable mRelayoutAndMakeVisible;
     private final Rect mInsets = new Rect();
 
     public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mLayoutInflater = LayoutInflater.from(context);
-        mRelayoutAndMakeVisible = new Runnable() {
-                public void run() {
-                    mTabs.requestLayout();
-                    mTabsContainer.setAlpha(1f);
-                }
-            };
     }
 
     /**
@@ -75,17 +61,17 @@
      * tabs manually).
      */
     void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) {
-        setOnTabChangedListener(null);
-        onTabChangedStart();
-        onTabChangedEnd(type);
-        setCurrentTabByTag(getTabTagForContentType(type));
-        setOnTabChangedListener(this);
+        mPagedView.setContentType(type);
+    }
+
+    public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) {
+        setContentTypeImmediate(type);
     }
 
     @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
-        FrameLayout.LayoutParams flp = (LayoutParams) mContent.getLayoutParams();
+        LayoutParams flp = (LayoutParams) mContent.getLayoutParams();
         flp.topMargin = insets.top;
         flp.bottomMargin = insets.bottom;
         flp.leftMargin = insets.left;
@@ -98,212 +84,12 @@
      */
     @Override
     protected void onFinishInflate() {
-        // Setup the tab host
-        setup();
-
-        final ViewGroup tabsContainer = (ViewGroup) findViewById(R.id.tabs_container);
-        final TabWidget tabs = getTabWidget();
-        final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView)
-                findViewById(R.id.apps_customize_pane_content);
-        mTabs = tabs;
-        mTabsContainer = tabsContainer;
-        mAppsCustomizePane = appsCustomizePane;
-        mAnimationBuffer = (FrameLayout) findViewById(R.id.animation_buffer);
-        mContent = (LinearLayout) findViewById(R.id.apps_customize_content);
-        if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
-
-        // Configure the tabs content factory to return the same paged view (that we change the
-        // content filter on)
-        TabContentFactory contentFactory = new TabContentFactory() {
-            public View createTabContent(String tag) {
-                return appsCustomizePane;
-            }
-        };
-
-        // Create the tabs
-        TextView tabView;
-        String label;
-        label = getContext().getString(R.string.all_apps_button_label);
-        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
-        tabView.setText(label);
-        tabView.setContentDescription(label);
-        addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
-        label = getContext().getString(R.string.widgets_tab_label);
-        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
-        tabView.setText(label);
-        tabView.setContentDescription(label);
-        addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
-        setOnTabChangedListener(this);
-
-        // Setup the key listener to jump between the last tab view and the market icon
-        AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener();
-        View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1);
-        lastTab.setOnKeyListener(keyListener);
-        View shopButton = findViewById(R.id.market_button);
-        shopButton.setOnKeyListener(keyListener);
-
-        // Hide the tab bar until we measure
-        mTabsContainer.setAlpha(0f);
+        mPagedView = (AppsCustomizePagedView) findViewById(R.id.apps_customize_pane_content);
+        mContent = findViewById(R.id.content);
     }
 
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        boolean remeasureTabWidth = (mTabs.getLayoutParams().width <= 0);
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        // Set the width of the tab list to the content width
-        if (remeasureTabWidth) {
-            int contentWidth = mAppsCustomizePane.getPageContentWidth();
-            if (contentWidth > 0 && mTabs.getLayoutParams().width != contentWidth) {
-                // Set the width and show the tab bar
-                mTabs.getLayoutParams().width = contentWidth;
-                mRelayoutAndMakeVisible.run();
-            }
-
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-    }
-
-     public boolean onInterceptTouchEvent(MotionEvent ev) {
-         // If we are mid transitioning to the workspace, then intercept touch events here so we
-         // can ignore them, otherwise we just let all apps handle the touch events.
-         if (mInTransition && mTransitioningToWorkspace) {
-             return true;
-         }
-         return super.onInterceptTouchEvent(ev);
-     };
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // Allow touch events to fall through to the workspace if we are transitioning there
-        if (mInTransition && mTransitioningToWorkspace) {
-            return super.onTouchEvent(event);
-        }
-
-        // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall
-        // through to the workspace and trigger showWorkspace()
-        if (event.getY() < mAppsCustomizePane.getBottom()) {
-            return true;
-        }
-        return super.onTouchEvent(event);
-    }
-
-    private void onTabChangedStart() {
-    }
-
-    private void reloadCurrentPage() {
-        mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
-        mAppsCustomizePane.requestFocus();
-    }
-
-    private void onTabChangedEnd(AppsCustomizePagedView.ContentType type) {
-        int bgAlpha = (int) (255 * (getResources().getInteger(
-            R.integer.config_appsCustomizeSpringLoadedBgAlpha) / 100f));
-        setBackgroundColor(Color.argb(bgAlpha, 0, 0, 0));
-        mAppsCustomizePane.setContentType(type);
-    }
-
-    @Override
-    public void onTabChanged(String tabId) {
-        final AppsCustomizePagedView.ContentType type = getContentTypeForTabTag(tabId);
-
-        // Animate the changing of the tab content by fading pages in and out
-        final Resources res = getResources();
-        final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
-
-        // We post a runnable here because there is a delay while the first page is loading and
-        // the feedback from having changed the tab almost feels better than having it stick
-        post(new Runnable() {
-            @Override
-            public void run() {
-                if (mAppsCustomizePane.getMeasuredWidth() <= 0 ||
-                        mAppsCustomizePane.getMeasuredHeight() <= 0) {
-                    reloadCurrentPage();
-                    return;
-                }
-
-                // Take the visible pages and re-parent them temporarily to mAnimatorBuffer
-                // and then cross fade to the new pages
-                int[] visiblePageRange = new int[2];
-                mAppsCustomizePane.getVisiblePages(visiblePageRange);
-                if (visiblePageRange[0] == -1 && visiblePageRange[1] == -1) {
-                    // If we can't get the visible page ranges, then just skip the animation
-                    reloadCurrentPage();
-                    return;
-                }
-                ArrayList<View> visiblePages = new ArrayList<View>();
-                for (int i = visiblePageRange[0]; i <= visiblePageRange[1]; i++) {
-                    visiblePages.add(mAppsCustomizePane.getPageAt(i));
-                }
-
-                // We want the pages to be rendered in exactly the same way as they were when
-                // their parent was mAppsCustomizePane -- so set the scroll on mAnimationBuffer
-                // to be exactly the same as mAppsCustomizePane, and below, set the left/top
-                // parameters to be correct for each of the pages
-                mAnimationBuffer.scrollTo(mAppsCustomizePane.getScrollX(), 0);
-
-                // mAppsCustomizePane renders its children in reverse order, so
-                // add the pages to mAnimationBuffer in reverse order to match that behavior
-                for (int i = visiblePages.size() - 1; i >= 0; i--) {
-                    View child = visiblePages.get(i);
-                    if (child instanceof AppsCustomizeCellLayout) {
-                        ((AppsCustomizeCellLayout) child).resetChildrenOnKeyListeners();
-                    } else if (child instanceof PagedViewGridLayout) {
-                        ((PagedViewGridLayout) child).resetChildrenOnKeyListeners();
-                    }
-                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(false);
-                    mAppsCustomizePane.removeView(child);
-                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(true);
-                    mAnimationBuffer.setAlpha(1f);
-                    mAnimationBuffer.setVisibility(View.VISIBLE);
-                    LayoutParams p = new FrameLayout.LayoutParams(child.getMeasuredWidth(),
-                            child.getMeasuredHeight());
-                    p.setMargins((int) child.getLeft(), (int) child.getTop(), 0, 0);
-                    mAnimationBuffer.addView(child, p);
-                }
-
-                // Toggle the new content
-                onTabChangedStart();
-                onTabChangedEnd(type);
-
-                // Animate the transition
-                ObjectAnimator outAnim = LauncherAnimUtils.ofFloat(mAnimationBuffer, "alpha", 0f);
-                outAnim.addListener(new AnimatorListenerAdapter() {
-                    private void clearAnimationBuffer() {
-                        mAnimationBuffer.setVisibility(View.GONE);
-                        PagedViewWidget.setRecyclePreviewsWhenDetachedFromWindow(false);
-                        mAnimationBuffer.removeAllViews();
-                        PagedViewWidget.setRecyclePreviewsWhenDetachedFromWindow(true);
-                    }
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        clearAnimationBuffer();
-                    }
-                    @Override
-                    public void onAnimationCancel(Animator animation) {
-                        clearAnimationBuffer();
-                    }
-                });
-                ObjectAnimator inAnim = LauncherAnimUtils.ofFloat(mAppsCustomizePane, "alpha", 1f);
-                inAnim.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        reloadCurrentPage();
-                    }
-                });
-
-                final AnimatorSet animSet = LauncherAnimUtils.createAnimatorSet();
-                animSet.playTogether(outAnim, inAnim);
-                animSet.setDuration(duration);
-                animSet.start();
-            }
-        });
-    }
-
-    public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) {
-        setOnTabChangedListener(null);
-        setCurrentTabByTag(getTabTagForContentType(type));
-        setOnTabChangedListener(this);
+    public String getContentTag() {
+        return getTabTagForContentType(mPagedView.getContentType());
     }
 
     /**
@@ -342,44 +128,41 @@
     }
 
     void reset() {
-        if (mInTransition) {
-            // Defer to after the transition to reset
-            mResetAfterTransition = true;
-        } else {
-            // Reset immediately
-            mAppsCustomizePane.reset();
+        // Reset immediately
+        mPagedView.reset();
+    }
+
+    public void onWindowVisible() {
+        if (getVisibility() == VISIBLE) {
+            mContent.setVisibility(VISIBLE);
+            // We unload the widget previews when the UI is hidden, so need to reload pages
+            // Load the current page synchronously, and the neighboring pages asynchronously
+            mPagedView.loadAssociatedPages(mPagedView.getCurrentPage(), true);
+            mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
         }
     }
 
-    private void enableAndBuildHardwareLayer() {
-        // isHardwareAccelerated() checks if we're attached to a window and if that
-        // window is HW accelerated-- we were sometimes not attached to a window
-        // and buildLayer was throwing an IllegalStateException
-        if (isHardwareAccelerated()) {
-            // Turn on hardware layers for performance
-            setLayerType(LAYER_TYPE_HARDWARE, null);
-
-            // force building the layer, so you don't get a blip early in an animation
-            // when the layer is created layer
-            buildLayer();
-        }
+    public void onTrimMemory() {
+        mContent.setVisibility(GONE);
+        // Clear the widget pages of all their subviews - this will trigger the widget previews
+        // to delete their bitmaps
+        mPagedView.clearAllWidgetPages();
     }
 
     @Override
-    public View getContent() {
-        View appsCustomizeContent = mAppsCustomizePane.getContent();
-        if (appsCustomizeContent != null) {
-            return appsCustomizeContent;
-        }
-        return mContent;
+    public ViewGroup getContent() {
+        return mPagedView;
+    }
+
+    public boolean isInTransition() {
+        return mInTransition;
     }
 
     /* LauncherTransitionable overrides */
     @Override
     public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
-        mAppsCustomizePane.onLauncherTransitionPrepare(l, animated, toWorkspace);
+        mPagedView.onLauncherTransitionPrepare(l, animated, toWorkspace);
         mInTransition = true;
-        mTransitioningToWorkspace = toWorkspace;
 
         if (toWorkspace) {
             // Going from All Apps -> Workspace
@@ -390,45 +173,38 @@
 
             // Make sure the current page is loaded (we start loading the side pages after the
             // transition to prevent slowing down the animation)
-            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
-        }
-
-        if (mResetAfterTransition) {
-            mAppsCustomizePane.reset();
-            mResetAfterTransition = false;
+            // TODO: revisit this
+            mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
         }
     }
 
     @Override
     public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
-        mAppsCustomizePane.onLauncherTransitionStart(l, animated, toWorkspace);
-        if (animated) {
-            enableAndBuildHardwareLayer();
-        }
-
-        // Dismiss the workspace cling
-        l.getLauncherClings().dismissWorkspaceCling(null);
+        mPagedView.onLauncherTransitionStart(l, animated, toWorkspace);
     }
 
     @Override
     public void onLauncherTransitionStep(Launcher l, float t) {
-        mAppsCustomizePane.onLauncherTransitionStep(l, t);
+        mPagedView.onLauncherTransitionStep(l, t);
     }
 
     @Override
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
-        mAppsCustomizePane.onLauncherTransitionEnd(l, animated, toWorkspace);
+        mPagedView.onLauncherTransitionEnd(l, animated, toWorkspace);
         mInTransition = false;
-        if (animated) {
-            setLayerType(LAYER_TYPE_NONE, null);
-        }
 
         if (!toWorkspace) {
-            // Show the all apps cling (if not already shown)
-            mAppsCustomizePane.showAllAppsCling();
             // Make sure adjacent pages are loaded (we wait until after the transition to
             // prevent slowing down the animation)
-            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
+            mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
+
+            // Opening apps, need to announce what page we are on.
+            AccessibilityManager am = (AccessibilityManager)
+                    getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+            if (am.isEnabled()) {
+                // Notify the user when the page changes
+                announceForAccessibility(mPagedView.getCurrentPageDescription());
+            }
 
             // Going from Workspace -> All Apps
             // NOTE: We should do this at the end since we check visibility state in some of the
@@ -459,25 +235,4 @@
             throw new RuntimeException("Failed; can't get z-order of views");
         }
     }
-
-    public void onWindowVisible() {
-        if (getVisibility() == VISIBLE) {
-            mContent.setVisibility(VISIBLE);
-            // We unload the widget previews when the UI is hidden, so need to reload pages
-            // Load the current page synchronously, and the neighboring pages asynchronously
-            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
-            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
-        }
-    }
-
-    public void onTrimMemory() {
-        mContent.setVisibility(GONE);
-        // Clear the widget pages of all their subviews - this will trigger the widget previews
-        // to delete their bitmaps
-        mAppsCustomizePane.clearAllWidgetPages();
-    }
-
-    boolean isTransitioning() {
-        return mInTransition;
-    }
 }
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
new file mode 100644
index 0000000..00f0cf3
--- /dev/null
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -0,0 +1,564 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.database.sqlite.SQLiteDatabase;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Patterns;
+
+import com.android.launcher3.LauncherProvider.SqlArguments;
+import com.android.launcher3.LauncherProvider.WorkspaceLoader;
+import com.android.launcher3.LauncherSettings.Favorites;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * This class contains contains duplication of functionality as found in
+ * LauncherProvider#DatabaseHelper. It has been isolated and differentiated in order
+ * to cleanly and separately represent AutoInstall default layout format and policy.
+ */
+public class AutoInstallsLayout implements WorkspaceLoader {
+    private static final String TAG = "AutoInstalls";
+    private static final boolean LOGD = true;
+
+    /** Marker action used to discover a package which defines launcher customization */
+    static final String ACTION_LAUNCHER_CUSTOMIZATION =
+            "android.autoinstalls.config.action.PLAY_AUTO_INSTALL";
+
+    private static final String LAYOUT_RES = "default_layout";
+
+    static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost,
+            LayoutParserCallback callback) {
+        Pair<String, Resources> customizationApkInfo = Utilities.findSystemApk(
+                ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager());
+        if (customizationApkInfo == null) {
+            return null;
+        }
+
+        String pkg = customizationApkInfo.first;
+        Resources res = customizationApkInfo.second;
+        int layoutId = res.getIdentifier(LAYOUT_RES, "xml", pkg);
+        if (layoutId == 0) {
+            Log.e(TAG, "Layout definition not found in package: " + pkg);
+            return null;
+        }
+        return new AutoInstallsLayout(context, appWidgetHost, callback, pkg, res, layoutId);
+    }
+
+    // Object Tags
+    private static final String TAG_WORKSPACE = "workspace";
+    private static final String TAG_APP_ICON = "appicon";
+    private static final String TAG_AUTO_INSTALL = "autoinstall";
+    private static final String TAG_FOLDER = "folder";
+    private static final String TAG_APPWIDGET = "appwidget";
+    private static final String TAG_SHORTCUT = "shortcut";
+    private static final String TAG_EXTRA = "extra";
+
+    private static final String ATTR_CONTAINER = "container";
+    private static final String ATTR_RANK = "rank";
+
+    private static final String ATTR_PACKAGE_NAME = "packageName";
+    private static final String ATTR_CLASS_NAME = "className";
+    private static final String ATTR_TITLE = "title";
+    private static final String ATTR_SCREEN = "screen";
+    private static final String ATTR_X = "x";
+    private static final String ATTR_Y = "y";
+    private static final String ATTR_SPAN_X = "spanX";
+    private static final String ATTR_SPAN_Y = "spanY";
+    private static final String ATTR_ICON = "icon";
+    private static final String ATTR_URL = "url";
+
+    // Style attrs -- "Extra"
+    private static final String ATTR_KEY = "key";
+    private static final String ATTR_VALUE = "value";
+
+    private static final String HOTSEAT_CONTAINER_NAME =
+            Favorites.containerToString(Favorites.CONTAINER_HOTSEAT);
+
+    private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
+            "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
+
+    private final Context mContext;
+    private final AppWidgetHost mAppWidgetHost;
+    private final LayoutParserCallback mCallback;
+
+    private final PackageManager mPackageManager;
+    private final ContentValues mValues;
+
+    private final Resources mRes;
+    private final int mLayoutId;
+
+    private SQLiteDatabase mDb;
+
+    public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
+            LayoutParserCallback callback, String packageName, Resources res, int layoutId) {
+        mContext = context;
+        mAppWidgetHost = appWidgetHost;
+        mCallback = callback;
+
+        mPackageManager = context.getPackageManager();
+        mValues = new ContentValues();
+
+        mRes = res;
+        mLayoutId = layoutId;
+    }
+
+    @Override
+    public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
+        mDb = db;
+        try {
+            return parseLayout(mRes, mLayoutId, screenIds);
+        } catch (XmlPullParserException | IOException | RuntimeException e) {
+            Log.w(TAG, "Got exception parsing layout.", e);
+            return -1;
+        }
+    }
+
+    private int parseLayout(Resources res, int layoutId, ArrayList<Long> screenIds)
+            throws XmlPullParserException, IOException {
+        final int hotseatAllAppsRank = LauncherAppState.getInstance()
+                .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
+
+        XmlResourceParser parser = res.getXml(layoutId);
+        beginDocument(parser, TAG_WORKSPACE);
+        final int depth = parser.getDepth();
+        int type;
+        HashMap<String, TagParser> tagParserMap = getLayoutElementsMap();
+        int count = 0;
+
+        while (((type = parser.next()) != XmlPullParser.END_TAG ||
+                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            mValues.clear();
+            final int container;
+            final long screenId;
+
+            if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) {
+                container = Favorites.CONTAINER_HOTSEAT;
+
+                // Hack: hotseat items are stored using screen ids
+                long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK));
+                screenId = (rank < hotseatAllAppsRank) ? rank : (rank + 1);
+
+            } else {
+                container = Favorites.CONTAINER_DESKTOP;
+                screenId = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
+
+                mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
+                mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
+            }
+
+            mValues.put(Favorites.CONTAINER, container);
+            mValues.put(Favorites.SCREEN, screenId);
+
+            TagParser tagParser = tagParserMap.get(parser.getName());
+            if (tagParser == null) {
+                if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
+                continue;
+            }
+            long newElementId = tagParser.parseAndAdd(parser, res);
+            if (newElementId >= 0) {
+                // Keep track of the set of screens which need to be added to the db.
+                if (!screenIds.contains(screenId) &&
+                        container == Favorites.CONTAINER_DESKTOP) {
+                    screenIds.add(screenId);
+                }
+                count++;
+            }
+        }
+        return count;
+    }
+
+    protected long addShortcut(String title, Intent intent, int type) {
+        long id = mCallback.generateNewItemId();
+        mValues.put(Favorites.INTENT, intent.toUri(0));
+        mValues.put(Favorites.TITLE, title);
+        mValues.put(Favorites.ITEM_TYPE, type);
+        mValues.put(Favorites.SPANX, 1);
+        mValues.put(Favorites.SPANY, 1);
+        mValues.put(Favorites._ID, id);
+        if (mCallback.insertAndCheck(mDb, mValues) < 0) {
+            return -1;
+        } else {
+            return id;
+        }
+    }
+
+    protected HashMap<String, TagParser> getFolderElementsMap() {
+        HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+        parsers.put(TAG_APP_ICON, new AppShortcutParser());
+        parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
+        return parsers;
+    }
+
+    protected HashMap<String, TagParser> getLayoutElementsMap() {
+        HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+        parsers.put(TAG_APP_ICON, new AppShortcutParser());
+        parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
+        parsers.put(TAG_FOLDER, new FolderParser());
+        parsers.put(TAG_APPWIDGET, new AppWidgetParser());
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
+        return parsers;
+    }
+
+    private interface TagParser {
+        /**
+         * Parses the tag and adds to the db
+         * @return the id of the row added or -1;
+         */
+        long parseAndAdd(XmlResourceParser parser, Resources res)
+                throws XmlPullParserException, IOException;
+    }
+
+    private class AppShortcutParser implements TagParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser, Resources res) {
+            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
+
+            if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) {
+                ActivityInfo info;
+                try {
+                    ComponentName cn;
+                    try {
+                        cn = new ComponentName(packageName, className);
+                        info = mPackageManager.getActivityInfo(cn, 0);
+                    } catch (PackageManager.NameNotFoundException nnfe) {
+                        String[] packages = mPackageManager.currentToCanonicalPackageNames(
+                                new String[] { packageName });
+                        cn = new ComponentName(packages[0], className);
+                        info = mPackageManager.getActivityInfo(cn, 0);
+                    }
+                    final Intent intent = new Intent(Intent.ACTION_MAIN, null)
+                        .addCategory(Intent.CATEGORY_LAUNCHER)
+                        .setComponent(cn)
+                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+                    return addShortcut(info.loadLabel(mPackageManager).toString(),
+                            intent, Favorites.ITEM_TYPE_APPLICATION);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Unable to add favorite: " + packageName + "/" + className, e);
+                }
+                return -1;
+            } else {
+                if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component or uri");
+                return -1;
+            }
+        }
+    }
+
+    private class AutoInstallParser implements TagParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser, Resources res) {
+            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
+            if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
+                if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component");
+                return -1;
+            }
+
+            mValues.put(Favorites.RESTORED, ShortcutInfo.FLAG_AUTOINTALL_ICON);
+            final Intent intent = new Intent(Intent.ACTION_MAIN, null)
+                .addCategory(Intent.CATEGORY_LAUNCHER)
+                .setComponent(new ComponentName(packageName, className))
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
+                    Favorites.ITEM_TYPE_APPLICATION);
+        }
+    }
+
+    private class ShortcutParser implements TagParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser, Resources res) {
+            final String url = getAttributeValue(parser, ATTR_URL);
+            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
+            final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0);
+
+            if (titleResId == 0 || iconId == 0) {
+                if (LOGD) Log.d(TAG, "Ignoring shortcut");
+                return -1;
+            }
+
+            if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
+                if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
+                return -1;
+            }
+            Drawable icon = res.getDrawable(iconId);
+            if (icon == null) {
+                if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon");
+                return -1;
+            }
+
+            ItemInfo.writeBitmap(mValues, Utilities.createIconBitmap(icon, mContext));
+            final Intent intent = new Intent(Intent.ACTION_VIEW, null)
+                .setData(Uri.parse(url))
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            return addShortcut(res.getString(titleResId), intent, Favorites.ITEM_TYPE_SHORTCUT);
+        }
+    }
+
+    private class AppWidgetParser implements TagParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser, Resources res)
+                throws XmlPullParserException, IOException {
+            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
+            if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
+                if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component");
+                return -1;
+            }
+
+            ComponentName cn = new ComponentName(packageName, className);
+            try {
+                mPackageManager.getReceiverInfo(cn, 0);
+            } catch (Exception e) {
+                String[] packages = mPackageManager.currentToCanonicalPackageNames(
+                        new String[] { packageName });
+                cn = new ComponentName(packages[0], className);
+                try {
+                    mPackageManager.getReceiverInfo(cn, 0);
+                } catch (Exception e1) {
+                    if (LOGD) Log.d(TAG, "Can't find widget provider: " + className);
+                    return -1;
+                }
+            }
+
+            mValues.put(Favorites.SPANX, getAttributeValue(parser, ATTR_SPAN_X));
+            mValues.put(Favorites.SPANY, getAttributeValue(parser, ATTR_SPAN_Y));
+
+            // Read the extras
+            Bundle extras = new Bundle();
+            int widgetDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                    parser.getDepth() > widgetDepth) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+
+                if (TAG_EXTRA.equals(parser.getName())) {
+                    String key = getAttributeValue(parser, ATTR_KEY);
+                    String value = getAttributeValue(parser, ATTR_VALUE);
+                    if (key != null && value != null) {
+                        extras.putString(key, value);
+                    } else {
+                        throw new RuntimeException("Widget extras must have a key and value");
+                    }
+                } else {
+                    throw new RuntimeException("Widgets can contain only extras");
+                }
+            }
+
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+            long insertedId = -1;
+            try {
+                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+
+                if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
+                    if (LOGD) Log.e(TAG, "Unable to bind app widget id " + cn);
+                    return -1;
+                }
+
+                mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
+                mValues.put(Favorites.APPWIDGET_ID, appWidgetId);
+                mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
+                mValues.put(Favorites._ID, mCallback.generateNewItemId());
+                insertedId = mCallback.insertAndCheck(mDb, mValues);
+                if (insertedId < 0) {
+                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+                    return insertedId;
+                }
+
+                // Send a broadcast to configure the widget
+                if (!extras.isEmpty()) {
+                    Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
+                    intent.setComponent(cn);
+                    intent.putExtras(extras);
+                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+                    mContext.sendBroadcast(intent);
+                }
+            } catch (RuntimeException ex) {
+                if (LOGD) Log.e(TAG, "Problem allocating appWidgetId", ex);
+            }
+            return insertedId;
+        }
+    }
+
+    private class FolderParser implements TagParser {
+        private final HashMap<String, TagParser> mFolderElements = getFolderElementsMap();
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser, Resources res)
+                throws XmlPullParserException, IOException {
+            final String title;
+            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
+            if (titleResId != 0) {
+                title = res.getString(titleResId);
+            } else {
+                title = mContext.getResources().getString(R.string.folder_name);
+            }
+
+            mValues.put(Favorites.TITLE, title);
+            mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER);
+            mValues.put(Favorites.SPANX, 1);
+            mValues.put(Favorites.SPANY, 1);
+            mValues.put(Favorites._ID, mCallback.generateNewItemId());
+            long folderId = mCallback.insertAndCheck(mDb, mValues);
+            if (folderId < 0) {
+                if (LOGD) Log.e(TAG, "Unable to add folder");
+                return -1;
+            }
+
+            final ContentValues myValues = new ContentValues(mValues);
+            ArrayList<Long> folderItems = new ArrayList<Long>();
+
+            int type;
+            int folderDepth = parser.getDepth();
+            while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                    parser.getDepth() > folderDepth) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                mValues.clear();
+                mValues.put(Favorites.CONTAINER, folderId);
+
+                TagParser tagParser = mFolderElements.get(parser.getName());
+                if (tagParser != null) {
+                    final long id = tagParser.parseAndAdd(parser, res);
+                    if (id >= 0) {
+                        folderItems.add(id);
+                    }
+                } else {
+                    throw new RuntimeException("Invalid folder item " + parser.getName());
+                }
+            }
+
+            long addedId = folderId;
+
+            // We can only have folders with >= 2 items, so we need to remove the
+            // folder and clean up if less than 2 items were included, or some
+            // failed to add, and less than 2 were actually added
+            if (folderItems.size() < 2) {
+                // Delete the folder
+                Uri uri = Favorites.getContentUri(folderId, false);
+                SqlArguments args = new SqlArguments(uri, null, null);
+                mDb.delete(args.table, args.where, args.args);
+                addedId = -1;
+
+                // If we have a single item, promote it to where the folder
+                // would have been.
+                if (folderItems.size() == 1) {
+                    final ContentValues childValues = new ContentValues();
+                    copyInteger(myValues, childValues, Favorites.CONTAINER);
+                    copyInteger(myValues, childValues, Favorites.SCREEN);
+                    copyInteger(myValues, childValues, Favorites.CELLX);
+                    copyInteger(myValues, childValues, Favorites.CELLY);
+
+                    addedId = folderItems.get(0);
+                    mDb.update(LauncherProvider.TABLE_FAVORITES, childValues,
+                            Favorites._ID + "=" + addedId, null);
+                }
+            }
+            return addedId;
+        }
+    }
+
+    private static final void beginDocument(XmlPullParser parser, String firstElementName)
+            throws XmlPullParserException, IOException {
+        int type;
+        while ((type = parser.next()) != XmlPullParser.START_TAG
+                && type != XmlPullParser.END_DOCUMENT);
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+
+        if (!parser.getName().equals(firstElementName)) {
+            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
+                    ", expected " + firstElementName);
+        }
+    }
+
+    /**
+     * Return attribute value, attempting launcher-specific namespace first
+     * before falling back to anonymous attribute.
+     */
+    private static String getAttributeValue(XmlResourceParser parser, String attribute) {
+        String value = parser.getAttributeValue(
+                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
+        if (value == null) {
+            value = parser.getAttributeValue(null, attribute);
+        }
+        return value;
+    }
+
+    /**
+     * Return attribute resource value, attempting launcher-specific namespace
+     * first before falling back to anonymous attribute.
+     */
+    private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
+            int defaultValue) {
+        int value = parser.getAttributeResourceValue(
+                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
+                defaultValue);
+        if (value == defaultValue) {
+            value = parser.getAttributeResourceValue(null, attribute, defaultValue);
+        }
+        return value;
+    }
+
+    public static interface LayoutParserCallback {
+        long generateNewItemId();
+
+        long insertAndCheck(SQLiteDatabase db, ContentValues values);
+    }
+
+    private static void copyInteger(ContentValues from, ContentValues to, String key) {
+        to.put(key, from.getAsInteger(key));
+    }
+}
diff --git a/src/com/android/launcher3/BorderCropDrawable.java b/src/com/android/launcher3/BorderCropDrawable.java
new file mode 100644
index 0000000..caf497d
--- /dev/null
+++ b/src/com/android/launcher3/BorderCropDrawable.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+public class BorderCropDrawable extends Drawable {
+
+    private final Drawable mChild;
+    private final Rect mBoundsShift;
+    private final Rect mPadding;
+
+    BorderCropDrawable(Drawable child, boolean cropLeft,
+            boolean cropTop, boolean cropRight, boolean cropBottom) {
+        mChild = child;
+
+        mBoundsShift = new Rect();
+        mPadding = new Rect();
+        mChild.getPadding(mPadding);
+
+        if (cropLeft) {
+            mBoundsShift.left = -mPadding.left;
+            mPadding.left = 0;
+        }
+        if (cropTop) {
+            mBoundsShift.top = -mPadding.top;
+            mPadding.top = 0;
+        }
+        if (cropRight) {
+            mBoundsShift.right = mPadding.right;
+            mPadding.right = 0;
+        }
+        if (cropBottom) {
+            mBoundsShift.bottom = mPadding.bottom;
+            mPadding.bottom = 0;
+        }
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        mChild.setBounds(
+                bounds.left + mBoundsShift.left,
+                bounds.top + mBoundsShift.top,
+                bounds.right + mBoundsShift.right,
+                bounds.bottom + mBoundsShift.bottom);
+    }
+
+    @Override
+    public boolean getPadding(Rect padding) {
+        padding.set(mPadding);
+        return (padding.left | padding.top | padding.right | padding.bottom) != 0;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mChild.draw(canvas);
+    }
+
+    @Override
+    public int getOpacity() {
+        return mChild.getOpacity();
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mChild.setAlpha(alpha);
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        mChild.setColorFilter(cf);
+    }
+}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index ee42904..a368796 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,16 +17,20 @@
 package com.android.launcher3;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.SparseArray;
 import android.util.TypedValue;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 import android.widget.TextView;
 
 /**
@@ -35,48 +39,57 @@
  * too aggressive.
  */
 public class BubbleTextView extends TextView {
-    static final float SHADOW_LARGE_RADIUS = 4.0f;
-    static final float SHADOW_SMALL_RADIUS = 1.75f;
-    static final float SHADOW_Y_OFFSET = 2.0f;
-    static final int SHADOW_LARGE_COLOUR = 0xDD000000;
-    static final int SHADOW_SMALL_COLOUR = 0xCC000000;
-    static final float PADDING_H = 8.0f;
+
+    private static SparseArray<Theme> sPreloaderThemes = new SparseArray<>(2);
+
+    private static final float SHADOW_LARGE_RADIUS = 4.0f;
+    private static final float SHADOW_SMALL_RADIUS = 1.75f;
+    private static final float SHADOW_Y_OFFSET = 2.0f;
+    private static final int SHADOW_LARGE_COLOUR = 0xDD000000;
+    private static final int SHADOW_SMALL_COLOUR = 0xCC000000;
     static final float PADDING_V = 3.0f;
 
-    private int mPrevAlpha = -1;
-
     private HolographicOutlineHelper mOutlineHelper;
-    private final Canvas mTempCanvas = new Canvas();
-    private final Rect mTempRect = new Rect();
-    private boolean mDidInvalidateForPressedState;
-    private Bitmap mPressedOrFocusedBackground;
-    private int mFocusedOutlineColor;
-    private int mFocusedGlowColor;
-    private int mPressedOutlineColor;
-    private int mPressedGlowColor;
+    private Bitmap mPressedBackground;
+
+    private float mSlop;
 
     private int mTextColor;
-    private boolean mShadowsEnabled = true;
+    private final boolean mCustomShadowsEnabled;
     private boolean mIsTextVisible;
 
+    // TODO: Remove custom background handling code, as no instance of BubbleTextView use any
+    // background.
     private boolean mBackgroundSizeChanged;
-    private Drawable mBackground;
+    private final Drawable mBackground;
 
     private boolean mStayPressed;
+    private boolean mIgnorePressedStateChange;
     private CheckLongPressHelper mLongPressHelper;
 
     public BubbleTextView(Context context) {
-        super(context);
-        init();
+        this(context, null, 0);
     }
 
     public BubbleTextView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
+        this(context, attrs, 0);
     }
 
     public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.BubbleTextView, defStyle, 0);
+        mCustomShadowsEnabled = a.getBoolean(R.styleable.BubbleTextView_customShadows, true);
+        a.recycle();
+
+        if (mCustomShadowsEnabled) {
+            // Draw the background itself as the parent is drawn twice.
+            mBackground = getBackground();
+            setBackground(null);
+        } else {
+            mBackground = null;
+        }
         init();
     }
 
@@ -87,34 +100,62 @@
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
         setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
-        setTextColor(getResources().getColor(R.color.workspace_icon_text_color));
     }
 
     private void init() {
         mLongPressHelper = new CheckLongPressHelper(this);
-        mBackground = getBackground();
 
         mOutlineHelper = HolographicOutlineHelper.obtain(getContext());
-
-        final Resources res = getContext().getResources();
-        mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor =
-            res.getColor(R.color.outline_color);
-
-        setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
+        if (mCustomShadowsEnabled) {
+            setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
+        }
     }
 
-    public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
+    public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
+            boolean setDefaultPadding) {
+        applyFromShortcutInfo(info, iconCache, setDefaultPadding, false);
+    }
+
+    public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
+            boolean setDefaultPadding, boolean promiseStateChanged) {
         Bitmap b = info.getIcon(iconCache);
         LauncherAppState app = LauncherAppState.getInstance();
+
+        FastBitmapDrawable iconDrawable = Utilities.createIconDrawable(b);
+        iconDrawable.setGhostModeEnabled(info.isDisabled);
+
+        setCompoundDrawables(null, iconDrawable, null, null);
+        if (setDefaultPadding) {
+            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+            setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
+        }
+        if (info.contentDescription != null) {
+            setContentDescription(info.contentDescription);
+        }
+        setText(info.title);
+        setTag(info);
+
+        if (promiseStateChanged || info.isPromise()) {
+            applyState(promiseStateChanged);
+        }
+    }
+
+    public void applyFromApplicationInfo(AppInfo info) {
+        LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
 
-        setCompoundDrawables(null,
-                Utilities.createIconDrawable(b), null, null);
+        Drawable topDrawable = Utilities.createIconDrawable(info.iconBitmap);
+        topDrawable.setBounds(0, 0, grid.allAppsIconSizePx, grid.allAppsIconSizePx);
+        setCompoundDrawables(null, topDrawable, null, null);
         setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
         setText(info.title);
+        if (info.contentDescription != null) {
+            setContentDescription(info.contentDescription);
+        }
         setTag(info);
     }
 
+
     @Override
     protected boolean setFrame(int left, int top, int right, int bottom) {
         if (getLeft() != left || getRight() != right || getTop() != top || getBottom() != bottom) {
@@ -137,90 +178,19 @@
     }
 
     @Override
-    protected void drawableStateChanged() {
-        if (isPressed()) {
-            // In this case, we have already created the pressed outline on ACTION_DOWN,
-            // so we just need to do an invalidate to trigger draw
-            if (!mDidInvalidateForPressedState) {
-                setCellLayoutPressedOrFocusedIcon();
-            }
-        } else {
-            // Otherwise, either clear the pressed/focused background, or create a background
-            // for the focused state
-            final boolean backgroundEmptyBefore = mPressedOrFocusedBackground == null;
-            if (!mStayPressed) {
-                mPressedOrFocusedBackground = null;
-            }
-            if (isFocused()) {
-                if (getLayout() == null) {
-                    // In some cases, we get focus before we have been layed out. Set the
-                    // background to null so that it will get created when the view is drawn.
-                    mPressedOrFocusedBackground = null;
-                } else {
-                    mPressedOrFocusedBackground = createGlowingOutline(
-                            mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor);
-                }
-                mStayPressed = false;
-                setCellLayoutPressedOrFocusedIcon();
-            }
-            final boolean backgroundEmptyNow = mPressedOrFocusedBackground == null;
-            if (!backgroundEmptyBefore && backgroundEmptyNow) {
-                setCellLayoutPressedOrFocusedIcon();
-            }
+    public void setPressed(boolean pressed) {
+        super.setPressed(pressed);
+
+        if (!mIgnorePressedStateChange) {
+            updateIconState();
         }
+    }
 
-        Drawable d = mBackground;
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
+    private void updateIconState() {
+        Drawable top = getCompoundDrawables()[1];
+        if (top instanceof FastBitmapDrawable) {
+            ((FastBitmapDrawable) top).setPressed(isPressed() || mStayPressed);
         }
-        super.drawableStateChanged();
-    }
-
-    /**
-     * Draw this BubbleTextView into the given Canvas.
-     *
-     * @param destCanvas the canvas to draw on
-     * @param padding the horizontal and vertical padding to use when drawing
-     */
-    private void drawWithPadding(Canvas destCanvas, int padding) {
-        final Rect clipRect = mTempRect;
-        getDrawingRect(clipRect);
-
-        // adjust the clip rect so that we don't include the text label
-        clipRect.bottom =
-            getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + getLayout().getLineTop(0);
-
-        // Draw the View into the bitmap.
-        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
-        // they set scrollX and scrollY to large values to achieve centered text
-        destCanvas.save();
-        destCanvas.scale(getScaleX(), getScaleY(),
-                (getWidth() + padding) / 2, (getHeight() + padding) / 2);
-        destCanvas.translate(-getScrollX() + padding / 2, -getScrollY() + padding / 2);
-        destCanvas.clipRect(clipRect, Op.REPLACE);
-        draw(destCanvas);
-        destCanvas.restore();
-    }
-
-    public void setGlowColor(int color) {
-        mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor = color;
-    }
-
-    /**
-     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
-     * Responsibility for the bitmap is transferred to the caller.
-     */
-    private Bitmap createGlowingOutline(Canvas canvas, int outlineColor, int glowColor) {
-        final int padding = mOutlineHelper.mMaxOuterBlurRadius;
-        final Bitmap b = Bitmap.createBitmap(
-                getWidth() + padding, getHeight() + padding, Bitmap.Config.ARGB_8888);
-
-        canvas.setBitmap(b);
-        drawWithPadding(canvas, padding);
-        mOutlineHelper.applyExtraThickExpensiveOutlineWithBlur(b, canvas, glowColor, outlineColor);
-        canvas.setBitmap(null);
-
-        return b;
     }
 
     @Override
@@ -231,20 +201,11 @@
 
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
-                // So that the pressed outline is visible immediately when isPressed() is true,
+                // So that the pressed outline is visible immediately on setStayPressed(),
                 // we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time
                 // to create it)
-                if (mPressedOrFocusedBackground == null) {
-                    mPressedOrFocusedBackground = createGlowingOutline(
-                            mTempCanvas, mPressedGlowColor, mPressedOutlineColor);
-                }
-                // Invalidate so the pressed state is visible, or set a flag so we know that we
-                // have to call invalidate as soon as the state is "pressed"
-                if (isPressed()) {
-                    mDidInvalidateForPressedState = true;
-                    setCellLayoutPressedOrFocusedIcon();
-                } else {
-                    mDidInvalidateForPressedState = false;
+                if (mPressedBackground == null) {
+                    mPressedBackground = mOutlineHelper.createMediumDropShadow(this);
                 }
 
                 mLongPressHelper.postCheckForLongPress();
@@ -254,11 +215,16 @@
                 // If we've touched down and up on an item, and it's still not "pressed", then
                 // destroy the pressed outline
                 if (!isPressed()) {
-                    mPressedOrFocusedBackground = null;
+                    mPressedBackground = null;
                 }
 
                 mLongPressHelper.cancelLongPress();
                 break;
+            case MotionEvent.ACTION_MOVE:
+                if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
+                    mLongPressHelper.cancelLongPress();
+                }
+                break;
         }
         return result;
     }
@@ -266,37 +232,52 @@
     void setStayPressed(boolean stayPressed) {
         mStayPressed = stayPressed;
         if (!stayPressed) {
-            mPressedOrFocusedBackground = null;
+            mPressedBackground = null;
         }
-        setCellLayoutPressedOrFocusedIcon();
-    }
 
-    void setCellLayoutPressedOrFocusedIcon() {
+        // Only show the shadow effect when persistent pressed state is set.
         if (getParent() instanceof ShortcutAndWidgetContainer) {
-            ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) getParent();
-            if (parent != null) {
-                CellLayout layout = (CellLayout) parent.getParent();
-                layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null);
-            }
+            CellLayout layout = (CellLayout) getParent().getParent();
+            layout.setPressedIcon(this, mPressedBackground, mOutlineHelper.shadowBitmapPadding);
         }
+
+        updateIconState();
     }
 
-    void clearPressedOrFocusedBackground() {
-        mPressedOrFocusedBackground = null;
-        setCellLayoutPressedOrFocusedIcon();
+    void clearPressedBackground() {
+        setPressed(false);
+        setStayPressed(false);
     }
 
-    Bitmap getPressedOrFocusedBackground() {
-        return mPressedOrFocusedBackground;
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (super.onKeyDown(keyCode, event)) {
+            // Pre-create shadow so show immediately on click.
+            if (mPressedBackground == null) {
+                mPressedBackground = mOutlineHelper.createMediumDropShadow(this);
+            }
+            return true;
+        }
+        return false;
     }
 
-    int getPressedOrFocusedBackgroundPadding() {
-        return mOutlineHelper.mMaxOuterBlurRadius / 2;
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        // Unlike touch events, keypress event propagate pressed state change immediately,
+        // without waiting for onClickHandler to execute. Disable pressed state changes here
+        // to avoid flickering.
+        mIgnorePressedStateChange = true;
+        boolean result = super.onKeyUp(keyCode, event);
+
+        mPressedBackground = null;
+        mIgnorePressedStateChange = false;
+        updateIconState();
+        return result;
     }
 
     @Override
     public void draw(Canvas canvas) {
-        if (!mShadowsEnabled) {
+        if (!mCustomShadowsEnabled) {
             super.draw(canvas);
             return;
         }
@@ -342,7 +323,14 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+
         if (mBackground != null) mBackground.setCallback(this);
+        Drawable top = getCompoundDrawables()[1];
+
+        if (top instanceof PreloadIconDrawable) {
+            ((PreloadIconDrawable) top).applyTheme(getPreloaderTheme());
+        }
+        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
     }
 
     @Override
@@ -357,10 +345,10 @@
         super.setTextColor(color);
     }
 
-    public void setShadowsEnabled(boolean enabled) {
-        mShadowsEnabled = enabled;
-        getPaint().clearShadowLayer();
-        invalidate();
+    @Override
+    public void setTextColor(ColorStateList colors) {
+        mTextColor = colors.getDefaultColor();
+        super.setTextColor(colors);
     }
 
     public void setTextVisibility(boolean visible) {
@@ -379,10 +367,6 @@
 
     @Override
     protected boolean onSetAlpha(int alpha) {
-        if (mPrevAlpha != alpha) {
-            mPrevAlpha = alpha;
-            super.onSetAlpha(alpha);
-        }
         return true;
     }
 
@@ -392,4 +376,45 @@
 
         mLongPressHelper.cancelLongPress();
     }
+
+    public void applyState(boolean promiseStateChanged) {
+        if (getTag() instanceof ShortcutInfo) {
+            ShortcutInfo info = (ShortcutInfo) getTag();
+            final boolean isPromise = info.isPromise();
+            final int progressLevel = isPromise ?
+                    ((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
+                            info.getInstallProgress() : 0)) : 100;
+
+            Drawable[] drawables = getCompoundDrawables();
+            Drawable top = drawables[1];
+            if (top != null) {
+                final PreloadIconDrawable preloadDrawable;
+                if (top instanceof PreloadIconDrawable) {
+                    preloadDrawable = (PreloadIconDrawable) top;
+                } else {
+                    preloadDrawable = new PreloadIconDrawable(top, getPreloaderTheme());
+                    setCompoundDrawables(drawables[0], preloadDrawable, drawables[2], drawables[3]);
+                }
+
+                preloadDrawable.setLevel(progressLevel);
+                if (promiseStateChanged) {
+                    preloadDrawable.maybePerformFinishedAnimation();
+                }
+            }
+        }
+    }
+
+    private Theme getPreloaderTheme() {
+        Object tag = getTag();
+        int style = ((tag != null) && (tag instanceof ShortcutInfo) &&
+                (((ShortcutInfo) tag).container >= 0)) ? R.style.PreloadIcon_Folder
+                        : R.style.PreloadIcon;
+        Theme theme = sPreloaderThemes.get(style);
+        if (theme == null) {
+            theme = getResources().newTheme();
+            theme.applyStyle(style, true);
+            sPreloaderThemes.put(style, theme);
+        }
+        return theme;
+    }
 }
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 2436a51..0ff1ef4 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -30,8 +30,6 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -73,11 +71,8 @@
     private int mWidthGap;
     private int mHeightGap;
     private int mMaxGap;
-    private boolean mScrollingTransformsDirty = false;
     private boolean mDropPending = false;
-
-    private final Rect mRect = new Rect();
-    private final CellInfo mCellInfo = new CellInfo();
+    private boolean mIsDragTarget = true;
 
     // These are temporary variables to prevent having to allocate a new object just to
     // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
@@ -128,7 +123,7 @@
     private int mDragOutlineCurrent = 0;
     private final Paint mDragOutlinePaint = new Paint();
 
-    private BubbleTextView mPressedOrFocusedIcon;
+    private final FastBitmapView mTouchFeedbackView;
 
     private HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new
             HashMap<CellLayout.LayoutParams, Animator>();
@@ -172,8 +167,6 @@
 
     private Rect mTempRect = new Rect();
 
-    private final static PorterDuffXfermode sAddBlendMode =
-            new PorterDuffXfermode(PorterDuff.Mode.ADD);
     private final static Paint sPaint = new Paint();
 
     public CellLayout(Context context) {
@@ -295,6 +288,9 @@
         mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
                 mCountX, mCountY);
 
+        mTouchFeedbackView = new FastBitmapView(context);
+        // Make the feedback view large enough to hold the blur bitmap.
+        addView(mTouchFeedbackView, (int) (grid.cellWidthPx * 1.5), (int) (grid.cellHeightPx * 1.5));
         addView(mShortcutsAndWidgets);
     }
 
@@ -341,14 +337,6 @@
         return mDropPending;
     }
 
-    private void invalidateBubbleTextView(BubbleTextView icon) {
-        final int padding = icon.getPressedOrFocusedBackgroundPadding();
-        invalidate(icon.getLeft() + getPaddingLeft() - padding,
-                icon.getTop() + getPaddingTop() - padding,
-                icon.getRight() + getPaddingLeft() + padding,
-                icon.getBottom() + getPaddingTop() + padding);
-    }
-
     void setOverScrollAmount(float r, boolean left) {
         if (left && mOverScrollForegroundDrawable != mOverScrollLeft) {
             mOverScrollForegroundDrawable = mOverScrollLeft;
@@ -362,24 +350,23 @@
         invalidate();
     }
 
-    void setPressedOrFocusedIcon(BubbleTextView icon) {
-        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
-        // requires an expanded clip rect (due to the glow's blur radius)
-        BubbleTextView oldIcon = mPressedOrFocusedIcon;
-        mPressedOrFocusedIcon = icon;
-        if (oldIcon != null) {
-            invalidateBubbleTextView(oldIcon);
-        }
-        if (mPressedOrFocusedIcon != null) {
-            invalidateBubbleTextView(mPressedOrFocusedIcon);
-        }
-    }
-
-    void setIsDragOverlapping(boolean isDragOverlapping) {
-        if (mIsDragOverlapping != isDragOverlapping) {
-            mIsDragOverlapping = isDragOverlapping;
-            setUseActiveGlowBackground(mIsDragOverlapping);
-            invalidate();
+    void setPressedIcon(BubbleTextView icon, Bitmap background, int padding) {
+        if (icon == null || background == null) {
+            mTouchFeedbackView.setBitmap(null);
+            mTouchFeedbackView.animate().cancel();
+        } else {
+            int offset = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
+                    - (mCountX * mCellWidth);
+            mTouchFeedbackView.setTranslationX(icon.getLeft() + (int) Math.ceil(offset / 2f)
+                    - padding);
+            mTouchFeedbackView.setTranslationY(icon.getTop() - padding);
+            if (mTouchFeedbackView.setBitmap(background)) {
+                mTouchFeedbackView.setAlpha(0);
+                mTouchFeedbackView.animate().alpha(1)
+                    .setDuration(FastBitmapDrawable.CLICK_FEEDBACK_DURATION)
+                    .setInterpolator(FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR)
+                    .start();
+            }
         }
     }
 
@@ -391,27 +378,26 @@
         mDrawBackground = false;
     }
 
+    void disableDragTarget() {
+        mIsDragTarget = false;
+    }
+
+    boolean isDragTarget() {
+        return mIsDragTarget;
+    }
+
+    void setIsDragOverlapping(boolean isDragOverlapping) {
+        if (mIsDragOverlapping != isDragOverlapping) {
+            mIsDragOverlapping = isDragOverlapping;
+            setUseActiveGlowBackground(mIsDragOverlapping);
+            invalidate();
+        }
+    }
+
     boolean getIsDragOverlapping() {
         return mIsDragOverlapping;
     }
 
-    protected void setOverscrollTransformsDirty(boolean dirty) {
-        mScrollingTransformsDirty = dirty;
-    }
-
-    protected void resetOverscrollTransforms() {
-        if (mScrollingTransformsDirty) {
-            setOverscrollTransformsDirty(false);
-            setTranslationX(0);
-            setRotationY(0);
-            // It doesn't matter if we pass true or false here, the important thing is that we
-            // pass 0, which results in the overscroll drawable not being drawn any more.
-            setOverScrollAmount(0, false);
-            setPivotX(getMeasuredWidth() / 2);
-            setPivotY(getMeasuredHeight() / 2);
-        }
-    }
-
     @Override
     protected void onDraw(Canvas canvas) {
         // When we're large, we are either drawn in a "hover" state (ie when dragging an item to
@@ -447,23 +433,6 @@
             }
         }
 
-        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
-        // requires an expanded clip rect (due to the glow's blur radius)
-        if (mPressedOrFocusedIcon != null) {
-            final int padding = mPressedOrFocusedIcon.getPressedOrFocusedBackgroundPadding();
-            final Bitmap b = mPressedOrFocusedIcon.getPressedOrFocusedBackground();
-            if (b != null) {
-                int offset = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() -
-                        (mCountX * mCellWidth);
-                int left = getPaddingLeft() + (int) Math.ceil(offset / 2f);
-                int top = getPaddingTop();
-                canvas.drawBitmap(b,
-                        mPressedOrFocusedIcon.getLeft() + left - padding,
-                        mPressedOrFocusedIcon.getTop() + top - padding,
-                        null);
-            }
-        }
-
         if (DEBUG_VISUALIZE_OCCUPIED) {
             int[] pt = new int[2];
             ColorDrawable cd = new ColorDrawable(Color.RED);
@@ -582,7 +551,15 @@
     }
 
     public void restoreInstanceState(SparseArray<Parcelable> states) {
-        dispatchRestoreInstanceState(states);
+        try {
+            dispatchRestoreInstanceState(states);
+        } catch (IllegalArgumentException ex) {
+            if (LauncherAppState.isDogfoodBuild()) {
+                throw ex;
+            }
+            // Mismatched viewId / viewType preventing restore. Skip restore on production builds.
+            Log.e(TAG, "Ignoring an error while restoring a view instance state", ex);
+        }
     }
 
     @Override
@@ -699,103 +676,17 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (getParent() instanceof Workspace) {
-            Workspace workspace = (Workspace) getParent();
-            mCellInfo.screenId = workspace.getIdForScreen(this);
-        }
-    }
-
-    public void setTagToCellInfoForPoint(int touchX, int touchY) {
-        final CellInfo cellInfo = mCellInfo;
-        Rect frame = mRect;
-        final int x = touchX + getScrollX();
-        final int y = touchY + getScrollY();
-        final int count = mShortcutsAndWidgets.getChildCount();
-
-        boolean found = false;
-        for (int i = count - 1; i >= 0; i--) {
-            final View child = mShortcutsAndWidgets.getChildAt(i);
-            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
-            if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) &&
-                    lp.isLockedToGrid) {
-                child.getHitRect(frame);
-
-                float scale = child.getScaleX();
-                frame = new Rect(child.getLeft(), child.getTop(), child.getRight(),
-                        child.getBottom());
-                // The child hit rect is relative to the CellLayoutChildren parent, so we need to
-                // offset that by this CellLayout's padding to test an (x,y) point that is relative
-                // to this view.
-                frame.offset(getPaddingLeft(), getPaddingTop());
-                frame.inset((int) (frame.width() * (1f - scale) / 2),
-                        (int) (frame.height() * (1f - scale) / 2));
-
-                if (frame.contains(x, y)) {
-                    cellInfo.cell = child;
-                    cellInfo.cellX = lp.cellX;
-                    cellInfo.cellY = lp.cellY;
-                    cellInfo.spanX = lp.cellHSpan;
-                    cellInfo.spanY = lp.cellVSpan;
-                    found = true;
-                    break;
-                }
-            }
-        }
-
-        mLastDownOnOccupiedCell = found;
-
-        if (!found) {
-            final int cellXY[] = mTmpXY;
-            pointToCellExact(x, y, cellXY);
-
-            cellInfo.cell = null;
-            cellInfo.cellX = cellXY[0];
-            cellInfo.cellY = cellXY[1];
-            cellInfo.spanX = 1;
-            cellInfo.spanY = 1;
-        }
-        setTag(cellInfo);
-    }
-
-    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // First we clear the tag to ensure that on every touch down we start with a fresh slate,
         // even in the case where we return early. Not clearing here was causing bugs whereby on
         // long-press we'd end up picking up an item from a previous drag operation.
-        final int action = ev.getAction();
-
-        if (action == MotionEvent.ACTION_DOWN) {
-            clearTagCellInfo();
-        }
-
         if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
             return true;
         }
 
-        if (action == MotionEvent.ACTION_DOWN) {
-            setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY());
-        }
-
         return false;
     }
 
-    private void clearTagCellInfo() {
-        final CellInfo cellInfo = mCellInfo;
-        cellInfo.cell = null;
-        cellInfo.cellX = -1;
-        cellInfo.cellY = -1;
-        cellInfo.spanX = 0;
-        cellInfo.spanY = 0;
-        setTag(cellInfo);
-    }
-
-    public CellInfo getTag() {
-        return (CellInfo) super.getTag();
-    }
-
     /**
      * Given a point, return the cell that strictly encloses that point
      * @param x X coordinate of the point
@@ -1049,6 +940,7 @@
     }
 
     public void setBackgroundAlphaMultiplier(float multiplier) {
+
         if (mBackgroundAlphaMultiplier != multiplier) {
             mBackgroundAlphaMultiplier = multiplier;
             invalidate();
@@ -1067,17 +959,11 @@
     }
 
     public void setShortcutAndWidgetAlpha(float alpha) {
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            getChildAt(i).setAlpha(alpha);
-        }
+        mShortcutsAndWidgets.setAlpha(alpha);
     }
 
     public ShortcutAndWidgetContainer getShortcutsAndWidgets() {
-        if (getChildCount() > 0) {
-            return (ShortcutAndWidgetContainer) getChildAt(0);
-        }
-        return null;
+        return mShortcutsAndWidgets;
     }
 
     public View getChildAt(int x, int y) {
@@ -3360,6 +3246,16 @@
         long screenId;
         long container;
 
+        CellInfo(View v, ItemInfo info) {
+            cell = v;
+            cellX = info.cellX;
+            cellY = info.cellY;
+            spanX = info.spanX;
+            spanY = info.spanY;
+            screenId = info.screenId;
+            container = info.container;
+        }
+
         @Override
         public String toString() {
             return "Cell[view=" + (cell == null ? "null" : cell.getClass())
diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java
deleted file mode 100644
index 185b49b..0000000
--- a/src/com/android/launcher3/Cling.java
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.*;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.FocusFinder;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-public class Cling extends FrameLayout implements Insettable, View.OnClickListener,
-        View.OnLongClickListener, View.OnTouchListener {
-
-    private static String FIRST_RUN_PORTRAIT = "first_run_portrait";
-    private static String FIRST_RUN_LANDSCAPE = "first_run_landscape";
-
-    private static String WORKSPACE_PORTRAIT = "workspace_portrait";
-    private static String WORKSPACE_LANDSCAPE = "workspace_landscape";
-    private static String WORKSPACE_LARGE = "workspace_large";
-    private static String WORKSPACE_CUSTOM = "workspace_custom";
-
-    private static String MIGRATION_PORTRAIT = "migration_portrait";
-    private static String MIGRATION_LANDSCAPE = "migration_landscape";
-
-    private static String MIGRATION_WORKSPACE_PORTRAIT = "migration_workspace_portrait";
-    private static String MIGRATION_WORKSPACE_LANDSCAPE = "migration_workspace_landscape";
-
-    private static String FOLDER_PORTRAIT = "folder_portrait";
-    private static String FOLDER_LANDSCAPE = "folder_landscape";
-    private static String FOLDER_LARGE = "folder_large";
-
-    private static float FIRST_RUN_CIRCLE_BUFFER_DPS = 60;
-    private static float WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 50;
-    private static float WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 60;
-    private static float WORKSPACE_CIRCLE_Y_OFFSET_DPS = 30;
-    private static float MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 42;
-    private static float MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 46;
-
-    private Launcher mLauncher;
-    private boolean mIsInitialized;
-    private String mDrawIdentifier;
-    private Drawable mBackground;
-
-    private int[] mTouchDownPt = new int[2];
-
-    private Drawable mFocusedHotseatApp;
-    private ComponentName mFocusedHotseatAppComponent;
-    private Rect mFocusedHotseatAppBounds;
-
-    private Paint mErasePaint;
-    private Paint mBorderPaint;
-    private Paint mBubblePaint;
-    private Paint mDotPaint;
-
-    private View mScrimView;
-    private int mBackgroundColor;
-
-    private final Rect mInsets = new Rect();
-
-    public Cling(Context context) {
-        this(context, null, 0);
-    }
-
-    public Cling(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public Cling(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Cling, defStyle, 0);
-        mDrawIdentifier = a.getString(R.styleable.Cling_drawIdentifier);
-        a.recycle();
-
-        setClickable(true);
-
-    }
-
-    void init(Launcher l, View scrim) {
-        if (!mIsInitialized) {
-            mLauncher = l;
-            mScrimView = scrim;
-            mBackgroundColor = 0xdd000000;
-            setOnLongClickListener(this);
-            setOnClickListener(this);
-            setOnTouchListener(this);
-
-            mErasePaint = new Paint();
-            mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
-            mErasePaint.setColor(0xFFFFFF);
-            mErasePaint.setAlpha(0);
-            mErasePaint.setAntiAlias(true);
-
-            mBorderPaint = new Paint();
-            mBorderPaint.setColor(0xFFFFFFFF);
-            mBorderPaint.setAntiAlias(true);
-
-            int circleColor = getResources().getColor(
-                    R.color.first_run_cling_circle_background_color);
-            mBubblePaint = new Paint();
-            mBubblePaint.setColor(circleColor);
-            mBubblePaint.setAntiAlias(true);
-
-            mDotPaint = new Paint();
-            mDotPaint.setColor(0x72BBED);
-            mDotPaint.setAntiAlias(true);
-
-            mIsInitialized = true;
-        }
-    }
-
-    void setFocusedHotseatApp(int drawableId, int appRank, ComponentName cn, String title,
-                              String description) {
-        // Get the app to draw
-        Resources r = getResources();
-        int appIconId = drawableId;
-        Hotseat hotseat = mLauncher.getHotseat();
-        if (hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() &&
-                !description.isEmpty()) {
-            // Set the app bounds
-            int x = hotseat.getCellXFromOrder(appRank);
-            int y = hotseat.getCellYFromOrder(appRank);
-            Rect pos = hotseat.getCellCoordinates(x, y);
-            LauncherAppState app = LauncherAppState.getInstance();
-            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-            mFocusedHotseatApp = getResources().getDrawable(appIconId);
-            mFocusedHotseatAppComponent = cn;
-            mFocusedHotseatAppBounds = new Rect(pos.left, pos.top,
-                    pos.left + Utilities.sIconTextureWidth,
-                    pos.top + Utilities.sIconTextureHeight);
-            Utilities.scaleRectAboutCenter(mFocusedHotseatAppBounds,
-                    ((float) grid.hotseatIconSizePx / grid.iconSizePx));
-
-            // Set the title
-            TextView v = (TextView) findViewById(R.id.focused_hotseat_app_title);
-            if (v != null) {
-                v.setText(title);
-            }
-
-            // Set the description
-            v = (TextView) findViewById(R.id.focused_hotseat_app_description);
-            if (v != null) {
-                v.setText(description);
-            }
-
-            // Show the bubble
-            View bubble = findViewById(R.id.focused_hotseat_app_bubble);
-            bubble.setVisibility(View.VISIBLE);
-        }
-    }
-
-    void updateMigrationWorkspaceBubblePosition() {
-        DisplayMetrics metrics = new DisplayMetrics();
-        mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
-
-        // Get the page indicator bounds
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
-
-        View bubble = findViewById(R.id.migration_workspace_cling_bubble);
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) bubble.getLayoutParams();
-        lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
-        bubble.requestLayout();
-    }
-
-    void show(boolean animate, int duration) {
-        setVisibility(View.VISIBLE);
-        setLayerType(View.LAYER_TYPE_HARDWARE, null);
-        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                mDrawIdentifier.equals(WORKSPACE_LARGE) ||
-                mDrawIdentifier.equals(WORKSPACE_CUSTOM) ||
-                mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
-            View content = getContent();
-            content.setAlpha(0f);
-            content.animate()
-                    .alpha(1f)
-                    .setDuration(duration)
-                    .setListener(null)
-                    .start();
-            setAlpha(1f);
-        } else {
-            if (animate) {
-                buildLayer();
-                setAlpha(0f);
-                animate()
-                    .alpha(1f)
-                    .setInterpolator(new AccelerateInterpolator())
-                    .setDuration(duration)
-                    .setListener(null)
-                    .start();
-            } else {
-                setAlpha(1f);
-            }
-        }
-
-        // Show the scrim if necessary
-        if (mScrimView != null) {
-            mScrimView.setVisibility(View.VISIBLE);
-            mScrimView.setAlpha(0f);
-            mScrimView.animate()
-                    .alpha(1f)
-                    .setDuration(duration)
-                    .setListener(null)
-                    .start();
-        }
-
-        setFocusableInTouchMode(true);
-        post(new Runnable() {
-            public void run() {
-                setFocusable(true);
-                requestFocus();
-            }
-        });
-    }
-
-    void hide(final int duration, final Runnable postCb) {
-        if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
-                mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE) ||
-                mDrawIdentifier.equals(MIGRATION_PORTRAIT) ||
-                mDrawIdentifier.equals(MIGRATION_LANDSCAPE)) {
-            View content = getContent();
-            content.animate()
-                .alpha(0f)
-                .setDuration(duration)
-                .setListener(new AnimatorListenerAdapter() {
-                    public void onAnimationEnd(Animator animation) {
-                        // We are about to trigger the workspace cling, so don't do anything else
-                        setVisibility(View.GONE);
-                        postCb.run();
-                    };
-                })
-                .start();
-        } else {
-            animate()
-                .alpha(0f)
-                .setDuration(duration)
-                .setListener(new AnimatorListenerAdapter() {
-                    public void onAnimationEnd(Animator animation) {
-                        // We are about to trigger the workspace cling, so don't do anything else
-                        setVisibility(View.GONE);
-                        postCb.run();
-                    };
-                })
-                .start();
-        }
-
-        // Show the scrim if necessary
-        if (mScrimView != null) {
-            mScrimView.animate()
-                .alpha(0f)
-                .setDuration(duration)
-                .setListener(new AnimatorListenerAdapter() {
-                    public void onAnimationEnd(Animator animation) {
-                        mScrimView.setVisibility(View.GONE);
-                    };
-                })
-                .start();
-        }
-    }
-
-    void cleanup() {
-        mBackground = null;
-        mIsInitialized = false;
-    }
-
-    void bringScrimToFront() {
-        if (mScrimView != null) {
-            mScrimView.bringToFront();
-        }
-    }
-
-    @Override
-    public void setInsets(Rect insets) {
-        mInsets.set(insets);
-        setPadding(insets.left, insets.top, insets.right, insets.bottom);
-    }
-
-    View getContent() {
-        return findViewById(R.id.content);
-    }
-
-    String getDrawIdentifier() {
-        return mDrawIdentifier;
-    }
-
-    @Override
-    public View focusSearch(int direction) {
-        return this.focusSearch(this, direction);
-    }
-
-    @Override
-    public View focusSearch(View focused, int direction) {
-        return FocusFinder.getInstance().findNextFocus(this, focused, direction);
-    }
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        return (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)
-                || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE)
-                || mDrawIdentifier.equals(WORKSPACE_LARGE)
-                || mDrawIdentifier.equals(WORKSPACE_CUSTOM));
-    }
-
-    @Override
-    public boolean onTouchEvent(android.view.MotionEvent event) {
-        if (mDrawIdentifier.equals(FOLDER_PORTRAIT) ||
-                   mDrawIdentifier.equals(FOLDER_LANDSCAPE) ||
-                   mDrawIdentifier.equals(FOLDER_LARGE)) {
-            Folder f = mLauncher.getWorkspace().getOpenFolder();
-            if (f != null) {
-                Rect r = new Rect();
-                f.getHitRect(r);
-                if (r.contains((int) event.getX(), (int) event.getY())) {
-                    return false;
-                }
-            }
-        }
-        return super.onTouchEvent(event);
-    };
-
-    @Override
-    public boolean onTouch(View v, MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mTouchDownPt[0] = (int) ev.getX();
-            mTouchDownPt[1] = (int) ev.getY();
-        }
-        return false;
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                mDrawIdentifier.equals(WORKSPACE_LARGE)) {
-            if (mFocusedHotseatAppBounds != null &&
-                mFocusedHotseatAppBounds.contains(mTouchDownPt[0], mTouchDownPt[1])) {
-                // Launch the activity that is being highlighted
-                Intent intent = new Intent(Intent.ACTION_MAIN);
-                intent.setComponent(mFocusedHotseatAppComponent);
-                intent.addCategory(Intent.CATEGORY_LAUNCHER);
-                mLauncher.startActivity(intent, null);
-                mLauncher.getLauncherClings().dismissWorkspaceCling(this);
-            }
-        }
-    }
-
-    @Override
-    public boolean onLongClick(View v) {
-        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                mDrawIdentifier.equals(WORKSPACE_LARGE)) {
-            mLauncher.getLauncherClings().dismissWorkspaceCling(null);
-            return true;
-        } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
-            mLauncher.getLauncherClings().dismissMigrationWorkspaceCling(null);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (mIsInitialized) {
-            canvas.save();
-
-            // Get the page indicator bounds
-            LauncherAppState app = LauncherAppState.getInstance();
-            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-            Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
-
-            // Get the background override if there is one
-            if (mBackground == null) {
-                if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
-                    mBackground = getResources().getDrawable(R.drawable.bg_cling5);
-                }
-            }
-            // Draw the background
-            Bitmap eraseBg = null;
-            Canvas eraseCanvas = null;
-            if (mScrimView != null) {
-                // Skip drawing the background
-                mScrimView.setBackgroundColor(mBackgroundColor);
-            } else if (mBackground != null) {
-                mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
-                mBackground.draw(canvas);
-            } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                    mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                    mDrawIdentifier.equals(WORKSPACE_LARGE) ||
-                    mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
-                    mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
-                // Initialize the draw buffer (to allow punching through)
-                eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
-                        Bitmap.Config.ARGB_8888);
-                eraseCanvas = new Canvas(eraseBg);
-                eraseCanvas.drawColor(mBackgroundColor);
-            } else {
-                canvas.drawColor(mBackgroundColor);
-            }
-
-            // Draw everything else
-            DisplayMetrics metrics = new DisplayMetrics();
-            mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
-            float alpha = getAlpha();
-            View content = getContent();
-            if (content != null) {
-                alpha *= content.getAlpha();
-            }
-            if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
-                    mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) {
-                // Draw the circle
-                View bubbleContent = findViewById(R.id.bubble_content);
-                Rect bubbleRect = new Rect();
-                bubbleContent.getGlobalVisibleRect(bubbleRect);
-                mBubblePaint.setAlpha((int) (255 * alpha));
-                float buffer = DynamicGrid.pxFromDp(FIRST_RUN_CIRCLE_BUFFER_DPS, metrics);
-                canvas.drawCircle(metrics.widthPixels / 2,
-                        bubbleRect.centerY(),
-                        (bubbleContent.getMeasuredWidth() + buffer) / 2,
-                        mBubblePaint);
-            } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                    mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                    mDrawIdentifier.equals(WORKSPACE_LARGE)) {
-                int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
-                // Draw the outer circle
-                mErasePaint.setAlpha(128);
-                eraseCanvas.drawCircle(metrics.widthPixels / 2,
-                        metrics.heightPixels / 2 - offset,
-                        DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
-                        mErasePaint);
-                // Draw the inner circle
-                mErasePaint.setAlpha(0);
-                eraseCanvas.drawCircle(metrics.widthPixels / 2,
-                        metrics.heightPixels / 2 - offset,
-                        DynamicGrid.pxFromDp(WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
-                        mErasePaint);
-                canvas.drawBitmap(eraseBg, 0, 0, null);
-                eraseCanvas.setBitmap(null);
-                eraseBg = null;
-
-                // Draw the focused hotseat app icon
-                if (mFocusedHotseatAppBounds != null && mFocusedHotseatApp != null) {
-                    mFocusedHotseatApp.setBounds(mFocusedHotseatAppBounds.left,
-                            mFocusedHotseatAppBounds.top, mFocusedHotseatAppBounds.right,
-                            mFocusedHotseatAppBounds.bottom);
-                    mFocusedHotseatApp.setAlpha((int) (255 * alpha));
-                    mFocusedHotseatApp.draw(canvas);
-                }
-            } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
-                    mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
-                int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
-                // Draw the outer circle
-                eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
-                        pageIndicatorBounds.centerY(),
-                        DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
-                        mBorderPaint);
-                // Draw the inner circle
-                mErasePaint.setAlpha(0);
-                eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
-                        pageIndicatorBounds.centerY(),
-                        DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
-                        mErasePaint);
-                canvas.drawBitmap(eraseBg, 0, 0, null);
-                eraseCanvas.setBitmap(null);
-                eraseBg = null;
-            }
-            canvas.restore();
-        }
-
-        // Draw the rest of the cling
-        super.dispatchDraw(canvas);
-    };
-}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 75d906b..05e8906 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -30,6 +30,9 @@
 import android.graphics.Rect;
 import android.graphics.drawable.TransitionDrawable;
 import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.UserManager;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -38,6 +41,9 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+
 import java.util.List;
 import java.util.Set;
 
@@ -125,11 +131,15 @@
     }
 
     private void setHoverColor() {
-        mCurrentDrawable.startTransition(mTransitionDuration);
+        if (mCurrentDrawable != null) {
+            mCurrentDrawable.startTransition(mTransitionDuration);
+        }
         setTextColor(mHoverColor);
     }
     private void resetHoverColor() {
-        mCurrentDrawable.resetTransition();
+        if (mCurrentDrawable != null) {
+            mCurrentDrawable.resetTransition();
+        }
         setTextColor(mOriginalTextColor);
     }
 
@@ -184,6 +194,17 @@
         if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) {
             isVisible = false;
         }
+        if (useUninstallLabel) {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                UserManager userManager = (UserManager)
+                        getContext().getSystemService(Context.USER_SERVICE);
+                Bundle restrictions = userManager.getUserRestrictions();
+                if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
+                        || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
+                    isVisible = false;
+                }
+            }
+        }
 
         if (useUninstallLabel) {
             setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
@@ -230,8 +251,11 @@
         final DragLayer dragLayer = mLauncher.getDragLayer();
         final Rect from = new Rect();
         dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+
+        int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
+        int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
         final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
-                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
+                width, height);
         final float scale = (float) to.width() / from.width();
 
         mSearchDropTargetBar.deferOnDragEnd();
@@ -279,25 +303,24 @@
         if (isAllAppsApplication(d.dragSource, item)) {
             // Uninstall the application if it is being dragged from AppsCustomize
             AppInfo appInfo = (AppInfo) item;
-            mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags);
+            mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags,
+                    appInfo.user);
         } else if (isUninstallFromWorkspace(d)) {
             ShortcutInfo shortcut = (ShortcutInfo) item;
             if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
                 final ComponentName componentName = shortcut.intent.getComponent();
                 final DragSource dragSource = d.dragSource;
-                int flags = AppInfo.initFlags(
-                    ShortcutInfo.getPackageInfo(getContext(), componentName.getPackageName()));
-                mWaitingForUninstall =
-                    mLauncher.startApplicationUninstallActivity(componentName, flags);
+                final UserHandleCompat user = shortcut.user;
+                mWaitingForUninstall = mLauncher.startApplicationUninstallActivity(
+                        componentName, shortcut.flags, user);
                 if (mWaitingForUninstall) {
                     final Runnable checkIfUninstallWasSuccess = new Runnable() {
                         @Override
                         public void run() {
                             mWaitingForUninstall = false;
                             String packageName = componentName.getPackageName();
-                            List<ResolveInfo> activities =
-                                    AllAppsList.findActivitiesForPackage(getContext(), packageName);
-                            boolean uninstallSuccessful = activities.size() == 0;
+                            boolean uninstallSuccessful = !AllAppsList.packageHasActivities(
+                                    getContext(), packageName, user);
                             if (dragSource instanceof Folder) {
                                 ((Folder) dragSource).
                                     onUninstallActivityReturned(uninstallSuccessful);
@@ -324,7 +347,7 @@
 
             final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
             final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
-            if (appWidgetHost != null) {
+            if ((appWidgetHost != null) && launcherAppWidgetInfo.isWidgetIdValid()) {
                 // Deleting an app widget ID is a void call but writes to disk before returning
                 // to the caller...
                 new AsyncTask<Void, Void, Void>() {
@@ -353,8 +376,11 @@
      */
     private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
             DragObject d, PointF vel, ViewConfiguration config) {
+
+        int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
+        int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
         final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
-                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
+                width, height);
         final Rect from = new Rect();
         dragLayer.getViewRectRelativeToSelf(d.dragView, from);
 
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a64d5e4..daf5556 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -31,9 +31,11 @@
 import android.view.Gravity;
 import android.view.Surface;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,16 +43,18 @@
 
 
 class DeviceProfileQuery {
+    DeviceProfile profile;
     float widthDps;
     float heightDps;
     float value;
     PointF dimens;
 
-    DeviceProfileQuery(float w, float h, float v) {
-        widthDps = w;
-        heightDps = h;
+    DeviceProfileQuery(DeviceProfile p, float v) {
+        widthDps = p.minWidthDps;
+        heightDps = p.minHeightDps;
         value = v;
-        dimens = new PointF(w, h);
+        dimens = new PointF(widthDps, heightDps);
+        profile = p;
     }
 }
 
@@ -65,11 +69,14 @@
     float numRows;
     float numColumns;
     float numHotseatIcons;
-    private float iconSize;
+    float iconSize;
     private float iconTextSize;
     private int iconDrawablePaddingOriginalPx;
     private float hotseatIconSize;
 
+    int defaultLayoutId;
+    int defaultNoAllAppsLayoutId;
+
     boolean isLandscape;
     boolean isTablet;
     boolean isLargeTablet;
@@ -88,7 +95,8 @@
 
     int overviewModeMinIconZoneHeightPx;
     int overviewModeMaxIconZoneHeightPx;
-    int overviewModeMaxBarWidthPx;
+    int overviewModeBarItemWidthPx;
+    int overviewModeBarSpacerWidthPx;
     float overviewModeIconZoneRatio;
     float overviewModeScaleFactor;
 
@@ -118,13 +126,17 @@
     int searchBarSpaceHeightPx;
     int searchBarHeightPx;
     int pageIndicatorHeightPx;
+    int allAppsButtonVisualSize;
 
     float dragViewScale;
 
+    int allAppsShortEdgeCount = -1;
+    int allAppsLongEdgeCount = -1;
+
     private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
 
     DeviceProfile(String n, float w, float h, float r, float c,
-                  float is, float its, float hs, float his) {
+                  float is, float its, float hs, float his, int dlId, int dnalId) {
         // Ensure that we have an odd number of hotseat items (since we need to place all apps)
         if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
             throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
@@ -139,6 +151,11 @@
         iconTextSize = its;
         numHotseatIcons = hs;
         hotseatIconSize = his;
+        defaultLayoutId = dlId;
+        defaultNoAllAppsLayoutId = dnalId;
+    }
+
+    DeviceProfile() {
     }
 
     DeviceProfile(Context context,
@@ -170,45 +187,51 @@
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
         overviewModeMaxIconZoneHeightPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
-        overviewModeMaxBarWidthPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_max_width);
+        overviewModeBarItemWidthPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
+        overviewModeBarSpacerWidthPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
         overviewModeIconZoneRatio =
                 res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
         overviewModeScaleFactor =
                 res.getInteger(R.integer.config_dynamic_grid_overview_scale_percentage) / 100f;
 
-        // Interpolate the rows
+        // Find the closes profile given the width/height
         for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows));
+            points.add(new DeviceProfileQuery(p, 0f));
         }
-        numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
-        // Interpolate the columns
-        points.clear();
-        for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns));
-        }
-        numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
-        // Interpolate the hotseat length
-        points.clear();
-        for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons));
-        }
-        numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+        DeviceProfile closestProfile = findClosestDeviceProfile(minWidth, minHeight, points);
+
+        // Snap to the closest row count
+        numRows = closestProfile.numRows;
+
+        // Snap to the closest column count
+        numColumns = closestProfile.numColumns;
+
+        // Snap to the closest hotseat size
+        numHotseatIcons = closestProfile.numHotseatIcons;
         hotseatAllAppsRank = (int) (numHotseatIcons / 2);
 
+        // Snap to the closest default layout id
+        defaultLayoutId = closestProfile.defaultLayoutId;
+
+        // Snap to the closest default no all-apps layout id
+        defaultNoAllAppsLayoutId = closestProfile.defaultNoAllAppsLayoutId;
+
         // Interpolate the icon size
         points.clear();
         for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize));
+            points.add(new DeviceProfileQuery(p, p.iconSize));
         }
         iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+
         // AllApps uses the original non-scaled icon size
         allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
 
         // Interpolate the icon text size
         points.clear();
         for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize));
+            points.add(new DeviceProfileQuery(p, p.iconTextSize));
         }
         iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
         iconDrawablePaddingOriginalPx =
@@ -219,14 +242,56 @@
         // Interpolate the hotseat icon size
         points.clear();
         for (DeviceProfile p : profiles) {
-            points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize));
+            points.add(new DeviceProfileQuery(p, p.hotseatIconSize));
         }
         // Hotseat
         hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
 
+        // If the partner customization apk contains any grid overrides, apply them
+        applyPartnerDeviceProfileOverrides(context, dm);
+
         // Calculate the remaining vars
         updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
         updateAvailableDimensions(context);
+        computeAllAppsButtonSize(context);
+    }
+
+    /**
+     * Apply any Partner customization grid overrides.
+     *
+     * Currently we support: all apps row / column count.
+     */
+    private void applyPartnerDeviceProfileOverrides(Context ctx, DisplayMetrics dm) {
+        Partner p = Partner.get(ctx.getPackageManager());
+        if (p != null) {
+            DeviceProfile partnerDp = p.getDeviceProfileOverride(dm);
+            if (partnerDp != null) {
+                if (partnerDp.numRows > 0 && partnerDp.numColumns > 0) {
+                    numRows = partnerDp.numRows;
+                    numColumns = partnerDp.numColumns;
+                }
+                if (partnerDp.allAppsShortEdgeCount > 0 && partnerDp.allAppsLongEdgeCount > 0) {
+                    allAppsShortEdgeCount = partnerDp.allAppsShortEdgeCount;
+                    allAppsLongEdgeCount = partnerDp.allAppsLongEdgeCount;
+                }
+                if (partnerDp.iconSize > 0) {
+                    iconSize = partnerDp.iconSize;
+                    // AllApps uses the original non-scaled icon size
+                    allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
+                }
+            }
+        }
+    }
+
+    /**
+     * Determine the exact visual footprint of the all apps button, taking into account scaling
+     * and internal padding of the drawable.
+     */
+    private void computeAllAppsButtonSize(Context context) {
+        Resources res = context.getResources();
+        float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f;
+        LauncherAppState app = LauncherAppState.getInstance();
+        allAppsButtonVisualSize = (int) (hotseatIconSizePx * (1 - padding));
     }
 
     void addCallback(DeviceProfileCallbacks cb) {
@@ -352,12 +417,17 @@
         int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount);
         int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount);
 
-        allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
-                (allAppsCellHeightPx + allAppsCellPaddingPx);
-        allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
-        allAppsNumCols = (availableWidthPx) /
-                (allAppsCellWidthPx + allAppsCellPaddingPx);
-        allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
+        if (allAppsShortEdgeCount > 0 && allAppsLongEdgeCount > 0) {
+            allAppsNumRows = isLandscape ? allAppsShortEdgeCount : allAppsLongEdgeCount;
+            allAppsNumCols = isLandscape ? allAppsLongEdgeCount : allAppsShortEdgeCount;
+        } else {
+            allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
+                    (allAppsCellHeightPx + allAppsCellPaddingPx);
+            allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
+            allAppsNumCols = (availableWidthPx) /
+                    (allAppsCellWidthPx + allAppsCellPaddingPx);
+            allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
+        }
     }
 
     void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
@@ -366,7 +436,11 @@
         isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
         isTablet = resources.getBoolean(R.bool.is_tablet);
         isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
-        isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+        } else {
+            isLayoutRtl = false;
+        }
         widthPx = wPx;
         heightPx = hPx;
         availableWidthPx = awPx;
@@ -389,6 +463,28 @@
         return (float) (1f / Math.pow(d, pow));
     }
 
+    /** Returns the closest device profile given the width and height and a list of profiles */
+    private DeviceProfile findClosestDeviceProfile(float width, float height,
+                                                   ArrayList<DeviceProfileQuery> points) {
+        return findClosestDeviceProfiles(width, height, points).get(0).profile;
+    }
+
+    /** Returns the closest device profiles ordered by closeness to the specified width and height */
+    private ArrayList<DeviceProfileQuery> findClosestDeviceProfiles(float width, float height,
+                                                   ArrayList<DeviceProfileQuery> points) {
+        final PointF xy = new PointF(width, height);
+
+        // Sort the profiles by their closeness to the dimensions
+        ArrayList<DeviceProfileQuery> pointsByNearness = points;
+        Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
+            public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
+                return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
+            }
+        });
+
+        return pointsByNearness;
+    }
+
     private float invDistWeightedInterpolate(float width, float height,
                 ArrayList<DeviceProfileQuery> points) {
         float sum = 0;
@@ -397,12 +493,8 @@
         float kNearestNeighbors = 3;
         final PointF xy = new PointF(width, height);
 
-        ArrayList<DeviceProfileQuery> pointsByNearness = points;
-        Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
-            public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
-                return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
-            }
-        });
+        ArrayList<DeviceProfileQuery> pointsByNearness = findClosestDeviceProfiles(width, height,
+                points);
 
         for (int i = 0; i < pointsByNearness.size(); ++i) {
             DeviceProfileQuery p = pointsByNearness.get(i);
@@ -478,9 +570,22 @@
     /** Returns the bounds of the workspace page indicators. */
     Rect getWorkspacePageIndicatorBounds(Rect insets) {
         Rect workspacePadding = getWorkspacePadding();
-        int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
-        return new Rect(workspacePadding.left, pageIndicatorTop,
-                widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
+        if (isLandscape && transposeLayoutWithOrientation) {
+            if (isLayoutRtl) {
+                return new Rect(workspacePadding.left, workspacePadding.top,
+                        workspacePadding.left + pageIndicatorHeightPx,
+                        heightPx - workspacePadding.bottom - insets.bottom);
+            } else {
+                int pageIndicatorLeft = widthPx - workspacePadding.right;
+                return new Rect(pageIndicatorLeft, workspacePadding.top,
+                        pageIndicatorLeft + pageIndicatorHeightPx,
+                        heightPx - workspacePadding.bottom - insets.bottom);
+            }
+        } else {
+            int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
+            return new Rect(workspacePadding.left, pageIndicatorTop,
+                    widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
+        }
     }
 
     /** Returns the workspace padding in the specified orientation */
@@ -539,7 +644,7 @@
             // In portrait, we want the pages spaced such that there is no
             // overhang of the previous / next page into the current page viewport.
             // We assume symmetrical padding in portrait mode.
-            return 2 * getWorkspacePadding().left;
+            return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left);
         }
     }
 
@@ -593,6 +698,21 @@
         return isVerticalBarLayout() || isLargeTablet();
     }
 
+    int getVisibleChildCount(ViewGroup parent) {
+        int visibleChildren = 0;
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            if (parent.getChildAt(i).getVisibility() != View.GONE) {
+                visibleChildren++;
+            }
+        }
+        return visibleChildren;
+    }
+
+    int calculateOverviewModeWidth(int visibleChildCount) {
+        return visibleChildCount * overviewModeBarItemWidthPx +
+                (visibleChildCount-1) * overviewModeBarSpacerWidthPx;
+    }
+
     public void layout(Launcher launcher) {
         FrameLayout.LayoutParams lp;
         Resources res = launcher.getResources();
@@ -605,10 +725,13 @@
             // Vertical search bar space
             lp.gravity = Gravity.TOP | Gravity.LEFT;
             lp.width = searchBarSpaceHeightPx;
-            lp.height = LayoutParams.MATCH_PARENT;
+            lp.height = LayoutParams.WRAP_CONTENT;
             searchBar.setPadding(
                     0, 2 * edgeMarginPx, 0,
                     2 * edgeMarginPx);
+
+            LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
+            targets.setOrientation(LinearLayout.VERTICAL);
         } else {
             // Horizontal search bar space
             lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
@@ -621,13 +744,6 @@
         }
         searchBar.setLayoutParams(lp);
 
-        // Layout the search bar
-        View qsbBar = launcher.getQsbBar();
-        LayoutParams vglp = qsbBar.getLayoutParams();
-        vglp.width = LayoutParams.MATCH_PARENT;
-        vglp.height = LayoutParams.MATCH_PARENT;
-        qsbBar.setLayoutParams(vglp);
-
         // Layout the voice proxy
         View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy);
         if (voiceButtonProxy != null) {
@@ -706,15 +822,19 @@
                     (allAppsIconSizePx / DynamicGrid.DEFAULT_ICON_SIZE_PX)));
             pageIndicator = host.findViewById(R.id.apps_customize_page_indicator);
             if (pageIndicator != null) {
-                lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
-                lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                lp.width = LayoutParams.WRAP_CONTENT;
-                lp.height = pageIndicatorHeight;
-                pageIndicator.setLayoutParams(lp);
+                LinearLayout.LayoutParams lllp = (LinearLayout.LayoutParams) pageIndicator.getLayoutParams();
+                lllp.width = LayoutParams.WRAP_CONTENT;
+                lllp.height = pageIndicatorHeight;
+                pageIndicator.setLayoutParams(lllp);
             }
 
             AppsCustomizePagedView pagedView = (AppsCustomizePagedView)
                     host.findViewById(R.id.apps_customize_pane_content);
+
+            FrameLayout fakePageContainer = (FrameLayout)
+                    host.findViewById(R.id.fake_page_container);
+            FrameLayout fakePage = (FrameLayout) host.findViewById(R.id.fake_page);
+
             padding = new Rect();
             if (pagedView != null) {
                 // Constrain the dimensions of all apps so that it does not span the full width
@@ -730,21 +850,35 @@
                 if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) {
                     padding.left = padding.right = gridPaddingLR;
                 }
+
                 // The icons are centered, so we can't just offset by the page indicator height
                 // because the empty space will actually be pageIndicatorHeight + paddingTB
                 padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB);
-                pagedView.setAllAppsPadding(padding);
+
                 pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight);
+                fakePage.setBackground(res.getDrawable(R.drawable.quantum_panel));
+
+                // Horizontal padding for the whole paged view
+                int pagedFixedViewPadding =
+                        res.getDimensionPixelSize(R.dimen.apps_customize_horizontal_padding);
+
+                padding.left += pagedFixedViewPadding;
+                padding.right += pagedFixedViewPadding;
+
+                pagedView.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+                fakePageContainer.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+
             }
         }
 
         // Layout the Overview Mode
-        View overviewMode = launcher.getOverviewPanel();
+        ViewGroup overviewMode = launcher.getOverviewPanel();
         if (overviewMode != null) {
             Rect r = getOverviewModeButtonBarRect();
             lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams();
             lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-            lp.width = Math.min(availableWidthPx, overviewModeMaxBarWidthPx);
+            lp.width = Math.min(availableWidthPx,
+                    calculateOverviewModeWidth(getVisibleChildCount(overviewMode)));
             lp.height = r.height();
             overviewMode.setLayoutParams(lp);
         }
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 4c3ea2a..6d0a2be 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -329,8 +329,8 @@
                     if (dragInfo != null &&
                             dragInfo.intent != null && info != null) {
                         ComponentName cn = dragInfo.intent.getComponent();
-                        boolean isSameComponent = cn.equals(info.componentName) ||
-                                packageNames.contains(cn.getPackageName());
+                        boolean isSameComponent = cn != null && (cn.equals(info.componentName) ||
+                                packageNames.contains(cn.getPackageName()));
                         if (isSameComponent) {
                             cancelDrag();
                             return;
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index ab0469d..a8a61ea 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -65,8 +65,6 @@
 
     private boolean mHoverPointClosesFolder = false;
     private Rect mHitRect = new Rect();
-    private int mWorkspaceIndex = -1;
-    private int mQsbIndex = -1;
     public static final int ANIMATION_END_DISAPPEAR = 0;
     public static final int ANIMATION_END_FADE_OUT = 1;
     public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
@@ -75,6 +73,22 @@
 
     private final Rect mInsets = new Rect();
 
+    private View mOverlayView;
+    private int mTopViewIndex;
+    private int mChildCountOnLastUpdate = -1;
+
+    // Darkening scrim
+    private Drawable mBackground;
+    private float mBackgroundAlpha = 0;
+
+    // Related to adjacent page hints
+    private boolean mInScrollArea;
+    private boolean mShowPageHints;
+    private Drawable mLeftHoverDrawable;
+    private Drawable mRightHoverDrawable;
+    private Drawable mLeftHoverDrawableActive;
+    private Drawable mRightHoverDrawableActive;
+
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -89,8 +103,12 @@
         setChildrenDrawingOrderEnabled(true);
         setOnHierarchyChangeListener(this);
 
-        mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo);
-        mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo);
+        final Resources res = getResources();
+        mLeftHoverDrawable = res.getDrawable(R.drawable.page_hover_left);
+        mRightHoverDrawable = res.getDrawable(R.drawable.page_hover_right);
+        mLeftHoverDrawableActive = res.getDrawable(R.drawable.page_hover_left_active);
+        mRightHoverDrawableActive = res.getDrawable(R.drawable.page_hover_right_active);
+        mBackground = res.getDrawable(R.drawable.apps_customize_bg);
     }
 
     public void setup(Launcher launcher, DragController controller) {
@@ -114,12 +132,30 @@
         return true; // I'll take it from here
     }
 
+    Rect getInsets() {
+        return mInsets;
+    }
+
     @Override
     public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
         super.addView(child, index, params);
         setInsets(child, mInsets, new Rect());
     }
 
+    public void showOverlayView(View overlayView) {
+        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        mOverlayView = overlayView;
+        addView(overlayView, lp);
+
+        // ensure that the overlay view stays on top. we can't use drawing order for this
+        // because in API level 16 touch dispatch doesn't respect drawing order.
+        mOverlayView.bringToFront();
+    }
+
+    public void dismissOverlayView() {
+        removeView(mOverlayView);
+    }
+
     private void setInsets(View child, Rect newInsets, Rect oldInsets) {
         final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
         if (child instanceof Insettable) {
@@ -168,8 +204,7 @@
         }
 
         Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
-        if (currentFolder != null && !mLauncher.getLauncherClings().isFolderClingVisible() &&
-                intercept) {
+        if (currentFolder != null && intercept) {
             if (currentFolder.isEditingName()) {
                 if (!isEventOverFolderTextRegion(currentFolder, ev)) {
                     currentFolder.dismissEditingName();
@@ -544,6 +579,10 @@
             // the drag view about the scaled child view.
             toY += Math.round(toScale * tv.getPaddingTop());
             toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2;
+            if (dragView.getDragVisualizeOffset() != null) {
+                toY -=  Math.round(toScale * dragView.getDragVisualizeOffset().y);
+            }
+
             toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
         } else if (child instanceof FolderIcon) {
             // Account for holographic blur padding on the drag view
@@ -762,6 +801,11 @@
 
     @Override
     public void onChildViewAdded(View parent, View child) {
+        if (mOverlayView != null) {
+            // ensure that the overlay view stays on top. we can't use drawing order for this
+            // because in API level 16 touch dispatch doesn't respect drawing order.
+            mOverlayView.bringToFront();
+        }
         updateChildIndices();
     }
 
@@ -770,39 +814,54 @@
         updateChildIndices();
     }
 
-    private void updateChildIndices() {
-        if (mLauncher != null) {
-            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
-            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
+    @Override
+    public void bringChildToFront(View child) {
+        super.bringChildToFront(child);
+        if (child != mOverlayView && mOverlayView != null) {
+            // ensure that the overlay view stays on top. we can't use drawing order for this
+            // because in API level 16 touch dispatch doesn't respect drawing order.
+            mOverlayView.bringToFront();
         }
+        updateChildIndices();
+    }
+
+    private void updateChildIndices() {
+        mTopViewIndex = -1;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            if (getChildAt(i) instanceof DragView) {
+                mTopViewIndex = i;
+            }
+        }
+        mChildCountOnLastUpdate = childCount;
     }
 
     @Override
     protected int getChildDrawingOrder(int childCount, int i) {
-        // TODO: We have turned off this custom drawing order because it now effects touch
-        // dispatch order. We need to sort that issue out and then decide how to go about this.
-        if (true || LauncherAppState.isScreenLandscape(getContext()) ||
-                mWorkspaceIndex == -1 || mQsbIndex == -1 ||
-                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
-            return i;
+        if (mChildCountOnLastUpdate != childCount) {
+            // between platform versions 17 and 18, behavior for onChildViewRemoved / Added changed.
+            // Pre-18, the child was not added / removed by the time of those callbacks. We need to
+            // force update our representation of things here to avoid crashing on pre-18 devices
+            // in certain instances.
+            updateChildIndices();
         }
 
-        // This ensures that the workspace is drawn above the hotseat and qsb,
-        // except when the workspace is drawing a background gradient, in which
-        // case we want the workspace to stay behind these elements.
-        if (i == mQsbIndex) {
-            return mWorkspaceIndex;
-        } else if (i == mWorkspaceIndex) {
-            return mQsbIndex;
-        } else {
+        // i represents the current draw iteration
+        if (mTopViewIndex == -1) {
+            // in general we do nothing
             return i;
+        } else if (i == childCount - 1) {
+            // if we have a top index, we return it when drawing last item (highest z-order)
+            return mTopViewIndex;
+        } else if (i < mTopViewIndex) {
+            return i;
+        } else {
+            // for indexes greater than the top index, we fetch one item above to shift for the
+            // displacement of the top index
+            return i + 1;
         }
     }
 
-    private boolean mInScrollArea;
-    private Drawable mLeftHoverDrawable;
-    private Drawable mRightHoverDrawable;
-
     void onEnterScrollArea(int direction) {
         mInScrollArea = true;
         invalidate();
@@ -813,6 +872,16 @@
         invalidate();
     }
 
+    void showPageHints() {
+        mShowPageHints = true;
+        invalidate();
+    }
+
+    void hidePageHints() {
+        mShowPageHints = false;
+        invalidate();
+    }
+
     /**
      * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
      */
@@ -822,31 +891,68 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
+        // Draw the background gradient below children.
+        if (mBackground != null && mBackgroundAlpha > 0.0f) {
+            int alpha = (int) (mBackgroundAlpha * 255);
+            mBackground.setAlpha(alpha);
+            mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
+            mBackground.draw(canvas);
+        }
 
-        if (mInScrollArea && !LauncherAppState.getInstance().isScreenLarge()) {
+        super.dispatchDraw(canvas);
+    }
+
+    private void drawPageHints(Canvas canvas) {
+        if (mShowPageHints) {
             Workspace workspace = mLauncher.getWorkspace();
             int width = getMeasuredWidth();
             Rect childRect = new Rect();
-            getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect);
+            getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1),
+                    childRect);
 
             int page = workspace.getNextPage();
             final boolean isRtl = isLayoutRtl();
             CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1);
             CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1);
 
-            if (leftPage != null && leftPage.getIsDragOverlapping()) {
-                mLeftHoverDrawable.setBounds(0, childRect.top,
-                        mLeftHoverDrawable.getIntrinsicWidth(), childRect.bottom);
-                mLeftHoverDrawable.draw(canvas);
-            } else if (rightPage != null && rightPage.getIsDragOverlapping()) {
-                mRightHoverDrawable.setBounds(width - mRightHoverDrawable.getIntrinsicWidth(),
+            if (leftPage != null && leftPage.isDragTarget()) {
+                Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ?
+                        mLeftHoverDrawableActive : mLeftHoverDrawable;
+                left.setBounds(0, childRect.top,
+                        left.getIntrinsicWidth(), childRect.bottom);
+                left.draw(canvas);
+            }
+            if (rightPage != null && rightPage.isDragTarget()) {
+                Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ?
+                        mRightHoverDrawableActive : mRightHoverDrawable;
+                right.setBounds(width - right.getIntrinsicWidth(),
                         childRect.top, width, childRect.bottom);
-                mRightHoverDrawable.draw(canvas);
+                right.draw(canvas);
             }
         }
     }
 
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        boolean ret = super.drawChild(canvas, child, drawingTime);
+
+        // We want to draw the page hints above the workspace, but below the drag view.
+        if (child instanceof Workspace) {
+            drawPageHints(canvas);
+        }
+        return ret;
+    }
+
+    public void setBackgroundAlpha(float alpha) {
+        if (alpha != mBackgroundAlpha) {
+            mBackgroundAlpha = alpha;
+            invalidate();
+        }
+    }
+
+    public float getBackgroundAlpha() {
+        return mBackgroundAlpha;
+    }
+
     public void setTouchCompleteListener(TouchCompleteListener listener) {
         mTouchCompleteListener = listener;
     }
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 3aced1f..94a07d7 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -60,32 +60,41 @@
         DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
         // Our phone profiles include the bar sizes in each orientation
         deviceProfiles.add(new DeviceProfile("Super Short Stubby",
-                255, 300,  2, 3,  48, 13, (hasAA ? 5 : 5), 48));
+                255, 300,  2, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         deviceProfiles.add(new DeviceProfile("Shorter Stubby",
-                255, 400,  3, 3,  48, 13, (hasAA ? 5 : 5), 48));
+                255, 400,  3, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         deviceProfiles.add(new DeviceProfile("Short Stubby",
-                275, 420,  3, 4,  48, 13, (hasAA ? 5 : 5), 48));
+                275, 420,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         deviceProfiles.add(new DeviceProfile("Stubby",
-                255, 450,  3, 4,  48, 13, (hasAA ? 5 : 5), 48));
+                255, 450,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         deviceProfiles.add(new DeviceProfile("Nexus S",
-                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48));
+                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         deviceProfiles.add(new DeviceProfile("Nexus 4",
-                359, 518,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56));
+                335, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
+        deviceProfiles.add(new DeviceProfile("Nexus 5",
+                359, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
+        deviceProfiles.add(new DeviceProfile("Large Phone",
+                406, 694,  5, 5,  64, 14.4f,  5, 56, R.xml.default_workspace_5x5,
+                R.xml.default_workspace_5x5_no_all_apps));
         // The tablet profile is odd in that the landscape orientation
         // also includes the nav bar on the side
         deviceProfiles.add(new DeviceProfile("Nexus 7",
-                575, 904,  5, 6,  72, 14.4f,  7, 60));
+                575, 904,  5, 6,  72, 14.4f,  7, 60, R.xml.default_workspace_5x6,
+                R.xml.default_workspace_5x6_no_all_apps));
         // Larger tablet profiles always have system bars on the top & bottom
         deviceProfiles.add(new DeviceProfile("Nexus 10",
-                727, 1207,  5, 6,  76, 14.4f,  7, 64));
-        /*
-        deviceProfiles.add(new DeviceProfile("Nexus 7",
-                600, 960,  5, 5,  72, 14.4f,  5, 60));
-        deviceProfiles.add(new DeviceProfile("Nexus 10",
-                800, 1280,  5, 5,  80, 14.4f, (hasAA ? 7 : 6), 64));
-         */
+                727, 1207,  5, 6,  76, 14.4f,  7, 64, R.xml.default_workspace_5x6,
+                R.xml.default_workspace_5x6_no_all_apps));
         deviceProfiles.add(new DeviceProfile("20-inch Tablet",
-                1527, 2527,  7, 7,  100, 20,  7, 72));
+                1527, 2527,  7, 7,  100, 20,  7, 72, R.xml.default_workspace_4x4,
+                R.xml.default_workspace_4x4_no_all_apps));
         mMinWidth = dpiFromPx(minWidthPx, dm);
         mMinHeight = dpiFromPx(minHeightPx, dm);
         mProfile = new DeviceProfile(context, deviceProfiles,
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 85e9020..ff02bbb 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -16,18 +16,61 @@
 
 package com.android.launcher3;
 
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.util.SparseArray;
 
 class FastBitmapDrawable extends Drawable {
-    private Bitmap mBitmap;
-    private int mAlpha;
+
+    static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() {
+
+        @Override
+        public float getInterpolation(float input) {
+            if (input < 0.05f) {
+                return input / 0.05f;
+            } else if (input < 0.3f){
+                return 1;
+            } else {
+                return (1 - input) / 0.7f;
+            }
+        }
+    };
+    static final long CLICK_FEEDBACK_DURATION = 2000;
+
+    private static final int PRESSED_BRIGHTNESS = 100;
+    private static ColorMatrix sGhostModeMatrix;
+    private static final ColorMatrix sTempMatrix = new ColorMatrix();
+
+    /**
+     * Store the brightness colors filters to optimize animations during icon press. This
+     * only works for non-ghost-mode icons.
+     */
+    private static final SparseArray<ColorFilter> sCachedBrightnessFilter =
+            new SparseArray<ColorFilter>();
+
+    private static final int GHOST_MODE_MIN_COLOR_RANGE = 130;
+
     private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+    private final Bitmap mBitmap;
+    private int mAlpha;
+
+    private int mBrightness = 0;
+    private boolean mGhostModeEnabled = false;
+
+    private boolean mPressed = false;
+    private ObjectAnimator mPressedAnimator;
 
     FastBitmapDrawable(Bitmap b) {
         mAlpha = 255;
@@ -44,7 +87,7 @@
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mPaint.setColorFilter(cf);
+        // No op
     }
 
     @Override
@@ -58,6 +101,7 @@
         mPaint.setAlpha(alpha);
     }
 
+    @Override
     public void setFilterBitmap(boolean filterBitmap) {
         mPaint.setFilterBitmap(filterBitmap);
         mPaint.setAntiAlias(filterBitmap);
@@ -69,12 +113,12 @@
 
     @Override
     public int getIntrinsicWidth() {
-        return getBounds().width();
+        return mBitmap.getWidth();
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return getBounds().height();
+        return mBitmap.getHeight();
     }
 
     @Override
@@ -90,4 +134,98 @@
     public Bitmap getBitmap() {
         return mBitmap;
     }
+
+    /**
+     * When enabled, the icon is grayed out and the contrast is increased to give it a 'ghost'
+     * appearance.
+     */
+    public void setGhostModeEnabled(boolean enabled) {
+        if (mGhostModeEnabled != enabled) {
+            mGhostModeEnabled = enabled;
+            updateFilter();
+        }
+    }
+
+    public void setPressed(boolean pressed) {
+        if (mPressed != pressed) {
+            mPressed = pressed;
+            if (mPressed) {
+                mPressedAnimator = ObjectAnimator
+                        .ofInt(this, "brightness", PRESSED_BRIGHTNESS)
+                        .setDuration(CLICK_FEEDBACK_DURATION);
+                mPressedAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR);
+                mPressedAnimator.start();
+            } else if (mPressedAnimator != null) {
+                mPressedAnimator.cancel();
+                setBrightness(0);
+            }
+        }
+        invalidateSelf();
+    }
+
+    public boolean isGhostModeEnabled() {
+        return mGhostModeEnabled;
+    }
+
+    public int getBrightness() {
+        return mBrightness;
+    }
+
+    public void setBrightness(int brightness) {
+        if (mBrightness != brightness) {
+            mBrightness = brightness;
+            updateFilter();
+            invalidateSelf();
+        }
+    }
+
+    private void updateFilter() {
+        if (mGhostModeEnabled) {
+            if (sGhostModeMatrix == null) {
+                sGhostModeMatrix = new ColorMatrix();
+                sGhostModeMatrix.setSaturation(0);
+
+                // For ghost mode, set the color range to [GHOST_MODE_MIN_COLOR_RANGE, 255]
+                float range = (255 - GHOST_MODE_MIN_COLOR_RANGE) / 255.0f;
+                sTempMatrix.set(new float[] {
+                        range, 0, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
+                        0, range, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
+                        0, 0, range, 0, GHOST_MODE_MIN_COLOR_RANGE,
+                        0, 0, 0, 1, 0 });
+                sGhostModeMatrix.preConcat(sTempMatrix);
+            }
+
+            if (mBrightness == 0) {
+                mPaint.setColorFilter(new ColorMatrixColorFilter(sGhostModeMatrix));
+            } else {
+                setBrightnessMatrix(sTempMatrix, mBrightness);
+                sTempMatrix.postConcat(sGhostModeMatrix);
+                mPaint.setColorFilter(new ColorMatrixColorFilter(sTempMatrix));
+            }
+        } else if (mBrightness != 0) {
+            ColorFilter filter = sCachedBrightnessFilter.get(mBrightness);
+            if (filter == null) {
+                filter = new PorterDuffColorFilter(Color.argb(mBrightness, 255, 255, 255),
+                        PorterDuff.Mode.SRC_ATOP);
+                sCachedBrightnessFilter.put(mBrightness, filter);
+            }
+            mPaint.setColorFilter(filter);
+        } else {
+            mPaint.setColorFilter(null);
+        }
+    }
+
+    private static void setBrightnessMatrix(ColorMatrix matrix, int brightness) {
+        // Brightness: C-new = C-old*(1-amount) + amount
+        float scale = 1 - brightness / 255.0f;
+        matrix.setScale(scale, scale, scale, 1);
+        float[] array = matrix.getArray();
+
+        // Add the amount to RGB components of the matrix, as per the above formula.
+        // Fifth elements in the array correspond to the constant being added to
+        // red, blue, green, and alpha channel respectively.
+        array[4] = brightness;
+        array[9] = brightness;
+        array[14] = brightness;
+    }
 }
diff --git a/src/com/android/launcher3/FastBitmapView.java b/src/com/android/launcher3/FastBitmapView.java
new file mode 100644
index 0000000..0937eb7
--- /dev/null
+++ b/src/com/android/launcher3/FastBitmapView.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.View;
+
+public class FastBitmapView extends View {
+
+    private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+    private Bitmap mBitmap;
+
+    public FastBitmapView(Context context) {
+        super(context);
+    }
+
+    /**
+     * Applies the new bitmap.
+     * @return true if the view was invalidated.
+     */
+    public boolean setBitmap(Bitmap b) {
+        if (b != mBitmap){
+            if (mBitmap != null) {
+                invalidate(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+            }
+            mBitmap = b;
+            if (mBitmap != null) {
+                invalidate(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mBitmap != null) {
+            canvas.drawBitmap(mBitmap, 0, 0, mPaint);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 4600985..d529b39 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -17,13 +17,13 @@
 package com.android.launcher3;
 
 import android.content.res.Configuration;
+import android.util.Log;
 import android.view.KeyEvent;
+import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.widget.ScrollView;
-import android.widget.TabHost;
-import android.widget.TabWidget;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -57,61 +57,16 @@
     }
 }
 
-/**
- * A keyboard listener we set on the last tab button in AppsCustomize to jump to then
- * market icon and vice versa.
- */
-class AppsCustomizeTabKeyEventListener implements View.OnKeyListener {
-    public boolean onKey(View v, int keyCode, KeyEvent event) {
-        return FocusHelper.handleAppsCustomizeTabKeyEvent(v, keyCode, event);
-    }
-}
-
 public class FocusHelper {
     /**
      * Private helper to get the parent TabHost in the view hiearchy.
      */
-    private static TabHost findTabHostParent(View v) {
+    private static AppsCustomizeTabHost findTabHostParent(View v) {
         ViewParent p = v.getParent();
-        while (p != null && !(p instanceof TabHost)) {
+        while (p != null && !(p instanceof AppsCustomizeTabHost)) {
             p = p.getParent();
         }
-        return (TabHost) p;
-    }
-
-    /**
-     * Handles key events in a AppsCustomize tab between the last tab view and the shop button.
-     */
-    static boolean handleAppsCustomizeTabKeyEvent(View v, int keyCode, KeyEvent e) {
-        final TabHost tabHost = findTabHostParent(v);
-        final ViewGroup contents = tabHost.getTabContentView();
-        final View shop = tabHost.findViewById(R.id.market_button);
-
-        final int action = e.getAction();
-        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
-        boolean wasHandled = false;
-        switch (keyCode) {
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-                if (handleKeyEvent) {
-                    // Select the shop button if we aren't on it
-                    if (v != shop) {
-                        shop.requestFocus();
-                    }
-                }
-                wasHandled = true;
-                break;
-            case KeyEvent.KEYCODE_DPAD_DOWN:
-                if (handleKeyEvent) {
-                    // Select the content view (down is handled by the tab key handler otherwise)
-                    if (v == shop) {
-                        contents.requestFocus();
-                        wasHandled = true;
-                    }
-                }
-                break;
-            default: break;
-        }
-        return wasHandled;
+        return (AppsCustomizeTabHost) p;
     }
 
     /**
@@ -134,8 +89,6 @@
 
         final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
         final PagedView container = (PagedView) parent.getParent();
-        final TabHost tabHost = findTabHostParent(container);
-        final TabWidget tabs = tabHost.getTabWidget();
         final int widgetIndex = parent.indexOfChild(w);
         final int widgetCount = parent.getChildCount();
         final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent));
@@ -194,8 +147,6 @@
                         int newWidgetIndex = ((y - 1) * cellCountX) + x;
                         child = parent.getChildAt(newWidgetIndex);
                         if (child != null) child.requestFocus();
-                    } else {
-                        tabs.requestFocus();
                     }
                 }
                 wasHandled = true;
@@ -294,8 +245,6 @@
         // Note we have an extra parent because of the
         // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
         final PagedView container = (PagedView) parentLayout.getParent();
-        final TabHost tabHost = findTabHostParent(container);
-        final TabWidget tabs = tabHost.getTabWidget();
         final int iconIndex = itemContainer.indexOfChild(v);
         final int itemCount = itemContainer.getChildCount();
         final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout));
@@ -317,13 +266,17 @@
                     // Select the previous icon or the last icon on the previous page
                     if (iconIndex > 0) {
                         itemContainer.getChildAt(iconIndex - 1).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                     } else {
                         if (pageIndex > 0) {
                             newParent = getAppsCustomizePage(container, pageIndex - 1);
                             if (newParent != null) {
                                 container.snapToPage(pageIndex - 1);
                                 child = newParent.getChildAt(newParent.getChildCount() - 1);
-                                if (child != null) child.requestFocus();
+                                if (child != null) {
+                                    child.requestFocus();
+                                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
+                                }
                             }
                         }
                     }
@@ -335,13 +288,17 @@
                     // Select the next icon or the first icon on the next page
                     if (iconIndex < (itemCount - 1)) {
                         itemContainer.getChildAt(iconIndex + 1).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                     } else {
                         if (pageIndex < (pageCount - 1)) {
                             newParent = getAppsCustomizePage(container, pageIndex + 1);
                             if (newParent != null) {
                                 container.snapToPage(pageIndex + 1);
                                 child = newParent.getChildAt(0);
-                                if (child != null) child.requestFocus();
+                                if (child != null) {
+                                    child.requestFocus();
+                                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
+                                }
                             }
                         }
                     }
@@ -354,31 +311,25 @@
                     if (y > 0) {
                         int newiconIndex = ((y - 1) * countX) + x;
                         itemContainer.getChildAt(newiconIndex).requestFocus();
-                    } else {
-                        tabs.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     }
                 }
                 wasHandled = true;
                 break;
             case KeyEvent.KEYCODE_DPAD_DOWN:
                 if (handleKeyEvent) {
-                    // Select the closest icon in the previous row, otherwise do nothing
+                    // Select the closest icon in the next row, otherwise do nothing
                     if (y < (countY - 1)) {
                         int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x);
-                        itemContainer.getChildAt(newiconIndex).requestFocus();
+                        int newIconY = newiconIndex / countX;
+                        if (newIconY != y) {
+                            itemContainer.getChildAt(newiconIndex).requestFocus();
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
+                        }
                     }
                 }
                 wasHandled = true;
                 break;
-            case KeyEvent.KEYCODE_ENTER:
-            case KeyEvent.KEYCODE_DPAD_CENTER:
-                if (handleKeyEvent) {
-                    // Simulate a click on the icon
-                    View.OnClickListener clickListener = (View.OnClickListener) container;
-                    clickListener.onClick(v);
-                }
-                wasHandled = true;
-                break;
             case KeyEvent.KEYCODE_PAGE_UP:
                 if (handleKeyEvent) {
                     // Select the first icon on the previous page, or the first icon on this page
@@ -388,10 +339,14 @@
                         if (newParent != null) {
                             container.snapToPage(pageIndex - 1);
                             child = newParent.getChildAt(0);
-                            if (child != null) child.requestFocus();
+                            if (child != null) {
+                                child.requestFocus();
+                                v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
+                            }
                         }
                     } else {
                         itemContainer.getChildAt(0).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     }
                 }
                 wasHandled = true;
@@ -405,10 +360,14 @@
                         if (newParent != null) {
                             container.snapToPage(pageIndex + 1);
                             child = newParent.getChildAt(0);
-                            if (child != null) child.requestFocus();
+                            if (child != null) {
+                                child.requestFocus();
+                                v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
+                            }
                         }
                     } else {
                         itemContainer.getChildAt(itemCount - 1).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                     }
                 }
                 wasHandled = true;
@@ -417,6 +376,7 @@
                 if (handleKeyEvent) {
                     // Select the first icon on this page
                     itemContainer.getChildAt(0).requestFocus();
+                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                 }
                 wasHandled = true;
                 break;
@@ -424,6 +384,7 @@
                 if (handleKeyEvent) {
                     // Select the last icon on this page
                     itemContainer.getChildAt(itemCount - 1).requestFocus();
+                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                 }
                 wasHandled = true;
                 break;
@@ -439,8 +400,8 @@
         if (!LauncherAppState.getInstance().isScreenLarge()) return false;
 
         final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
-        final TabHost tabHost = findTabHostParent(parent);
-        final ViewGroup contents = tabHost.getTabContentView();
+        final AppsCustomizeTabHost tabHost = findTabHostParent(parent);
+        final ViewGroup contents = tabHost.getContent();
         final int tabCount = parent.getTabCount();
         final int tabIndex = parent.getChildTabIndex(v);
 
@@ -490,53 +451,56 @@
      * Handles key events in the workspace hotseat (bottom of the screen).
      */
     static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
-        final ViewGroup parent = (ViewGroup) v.getParent();
-        final ViewGroup launcher = (ViewGroup) parent.getParent();
-        final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
-        final int buttonIndex = parent.indexOfChild(v);
-        final int buttonCount = parent.getChildCount();
-        final int pageIndex = workspace.getCurrentPage();
+        ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
+        final CellLayout layout = (CellLayout) parent.getParent();
 
         // NOTE: currently we don't special case for the phone UI in different
-        // orientations, even though the hotseat is on the side in landscape mode.  This
+        // orientations, even though the hotseat is on the side in landscape mode. This
         // is to ensure that accessibility consistency is maintained across rotations.
-
         final int action = e.getAction();
         final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
         boolean wasHandled = false;
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_LEFT:
                 if (handleKeyEvent) {
-                    // Select the previous button, otherwise snap to the previous page
-                    if (buttonIndex > 0) {
-                        parent.getChildAt(buttonIndex - 1).requestFocus();
-                    } else {
-                        workspace.snapToPage(pageIndex - 1);
+                    ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+                    int myIndex = views.indexOf(v);
+                    // Select the previous button, otherwise do nothing
+                    if (myIndex > 0) {
+                        views.get(myIndex - 1).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                     }
                 }
                 wasHandled = true;
                 break;
             case KeyEvent.KEYCODE_DPAD_RIGHT:
                 if (handleKeyEvent) {
-                    // Select the next button, otherwise snap to the next page
-                    if (buttonIndex < (buttonCount - 1)) {
-                        parent.getChildAt(buttonIndex + 1).requestFocus();
-                    } else {
-                        workspace.snapToPage(pageIndex + 1);
+                    ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+                    int myIndex = views.indexOf(v);
+                    // Select the next button, otherwise do nothing
+                    if (myIndex < views.size() - 1) {
+                        views.get(myIndex + 1).requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                     }
                 }
                 wasHandled = true;
                 break;
             case KeyEvent.KEYCODE_DPAD_UP:
                 if (handleKeyEvent) {
-                    // Select the first bubble text view in the current page of the workspace
-                    final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
-                    final ShortcutAndWidgetContainer children = layout.getShortcutsAndWidgets();
-                    final View newIcon = getIconInDirection(layout, children, -1, 1);
-                    if (newIcon != null) {
-                        newIcon.requestFocus();
-                    } else {
-                        workspace.requestFocus();
+                    final Workspace workspace = (Workspace)
+                            v.getRootView().findViewById(R.id.workspace);
+                    if (workspace != null) {
+                        int pageIndex = workspace.getCurrentPage();
+                        CellLayout topLayout = (CellLayout) workspace.getChildAt(pageIndex);
+                        ShortcutAndWidgetContainer children = topLayout.getShortcutsAndWidgets();
+                        final View newIcon = getIconInDirection(layout, children, -1, 1);
+                        // Select the first bubble text view in the current page of the workspace
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
+                        } else {
+                            workspace.requestFocus();
+                        }
                     }
                 }
                 wasHandled = true;
@@ -555,8 +519,8 @@
      */
     private static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
             ViewGroup container, int i) {
-        ViewGroup parent = (ViewGroup) container.getChildAt(i);
-        return (ShortcutAndWidgetContainer) parent.getChildAt(0);
+        CellLayout parent = (CellLayout) container.getChildAt(i);
+        return parent.getShortcutsAndWidgets();
     }
 
     /**
@@ -665,7 +629,7 @@
         final CellLayout layout = (CellLayout) parent.getParent();
         final Workspace workspace = (Workspace) layout.getParent();
         final ViewGroup launcher = (ViewGroup) workspace.getParent();
-        final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.qsb_bar);
+        final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
         final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat);
         int pageIndex = workspace.indexOfChild(layout);
         int pageCount = workspace.getChildCount();
@@ -680,6 +644,7 @@
                     View newIcon = getIconInDirection(layout, parent, v, -1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                     } else {
                         if (pageIndex > 0) {
                             parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
@@ -691,6 +656,7 @@
                                 // Snap to the previous page
                                 workspace.snapToPage(pageIndex - 1);
                             }
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                         }
                     }
                 }
@@ -702,6 +668,7 @@
                     View newIcon = getIconInDirection(layout, parent, v, 1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                     } else {
                         if (pageIndex < (pageCount - 1)) {
                             parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
@@ -712,6 +679,7 @@
                                 // Snap to the next page
                                 workspace.snapToPage(pageIndex + 1);
                             }
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                         }
                     }
                 }
@@ -727,6 +695,7 @@
                     } else {
                         tabs.requestFocus();
                     }
+                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                 }
                 break;
             case KeyEvent.KEYCODE_DPAD_DOWN:
@@ -735,9 +704,11 @@
                     View newIcon = getClosestIconOnLine(layout, parent, v, 1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                         wasHandled = true;
                     } else if (hotseat != null) {
                         hotseat.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                     }
                 }
                 break;
@@ -754,10 +725,12 @@
                             // Snap to the previous page
                             workspace.snapToPage(pageIndex - 1);
                         }
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     } else {
                         View newIcon = getIconInDirection(layout, parent, -1, 1);
                         if (newIcon != null) {
                             newIcon.requestFocus();
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                         }
                     }
                 }
@@ -776,11 +749,13 @@
                             // Snap to the next page
                             workspace.snapToPage(pageIndex + 1);
                         }
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                     } else {
                         View newIcon = getIconInDirection(layout, parent,
                                 parent.getChildCount(), -1);
                         if (newIcon != null) {
                             newIcon.requestFocus();
+                            v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                         }
                     }
                 }
@@ -792,6 +767,7 @@
                     View newIcon = getIconInDirection(layout, parent, -1, 1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     }
                 }
                 wasHandled = true;
@@ -803,6 +779,7 @@
                             parent.getChildCount(), -1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                     }
                 }
                 wasHandled = true;
@@ -832,6 +809,7 @@
                     View newIcon = getIconInDirection(layout, parent, v, -1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                     }
                 }
                 wasHandled = true;
@@ -845,6 +823,7 @@
                     } else {
                         title.requestFocus();
                     }
+                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                 }
                 wasHandled = true;
                 break;
@@ -854,6 +833,7 @@
                     View newIcon = getClosestIconOnLine(layout, parent, v, -1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     }
                 }
                 wasHandled = true;
@@ -867,6 +847,7 @@
                     } else {
                         title.requestFocus();
                     }
+                    v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                 }
                 wasHandled = true;
                 break;
@@ -876,6 +857,7 @@
                     View newIcon = getIconInDirection(layout, parent, -1, 1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
                     }
                 }
                 wasHandled = true;
@@ -887,6 +869,7 @@
                             parent.getChildCount(), -1);
                     if (newIcon != null) {
                         newIcon.requestFocus();
+                        v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
                     }
                 }
                 wasHandled = true;
diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java
new file mode 100644
index 0000000..12b7a40
--- /dev/null
+++ b/src/com/android/launcher3/FocusIndicatorView.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewParent;
+
+public class FocusIndicatorView extends View implements View.OnFocusChangeListener {
+
+    // It can be any number >0. The view is resized using scaleX and scaleY.
+    static final int DEFAULT_LAYOUT_SIZE = 100;
+    private static final float MIN_VISIBLE_ALPHA = 0.2f;
+
+    private static final int[] sTempPos = new int[2];
+    private static final int[] sTempShift = new int[2];
+
+    private final int[] mIndicatorPos = new int[2];
+    private final int[] mTargetViewPos = new int[2];
+
+    private View mLastFocusedView;
+    private boolean mInitiated;
+
+    private Pair<View, Boolean> mPendingCall;
+
+    public FocusIndicatorView(Context context) {
+        this(context, null);
+    }
+
+    public FocusIndicatorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setAlpha(0);
+        setBackgroundColor(getResources().getColor(R.color.focused_background));
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+
+        // Redraw if it is already showing. This avoids a bug where the height changes by a small
+        // amount on connecting/disconnecting a bluetooth keyboard.
+        if (mLastFocusedView != null) {
+            mPendingCall = Pair.create(mLastFocusedView, Boolean.TRUE);
+            invalidate();
+        }
+    }
+
+    @Override
+    public void onFocusChange(View v, boolean hasFocus) {
+        mPendingCall = null;
+        if (!mInitiated && (getWidth() == 0)) {
+            // View not yet laid out. Wait until the view is ready to be drawn, so that be can
+            // get the location on screen.
+            mPendingCall = Pair.create(v, hasFocus);
+            invalidate();
+            return;
+        }
+
+        if (!mInitiated) {
+            getLocationRelativeToParentPagedView(this, mIndicatorPos);
+            mInitiated = true;
+        }
+
+        if (hasFocus) {
+            int indicatorWidth = getWidth();
+            int indicatorHeight = getHeight();
+
+            float scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
+            float scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
+
+            getLocationRelativeToParentPagedView(v, mTargetViewPos);
+            float x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - scaleX) * indicatorWidth / 2;
+            float y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - scaleY) * indicatorHeight / 2;
+
+            if (getAlpha() > MIN_VISIBLE_ALPHA) {
+                animate()
+                .translationX(x)
+                .translationY(y)
+                .scaleX(scaleX)
+                .scaleY(scaleY)
+                .alpha(1);
+            } else {
+                setTranslationX(x);
+                setTranslationY(y);
+                setScaleX(scaleX);
+                setScaleY(scaleY);
+                animate().alpha(1);
+            }
+            mLastFocusedView = v;
+        } else {
+            if (mLastFocusedView == v) {
+                mLastFocusedView = null;
+                animate().alpha(0);
+            }
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mPendingCall != null) {
+            onFocusChange(mPendingCall.first, mPendingCall.second);
+        }
+    }
+
+    /**
+     * Gets the location of a view relative in the window, off-setting any shift due to
+     * page view scroll
+     */
+    private static void getLocationRelativeToParentPagedView(View v, int[] pos) {
+        getPagedViewScrollShift(v, sTempShift);
+        v.getLocationInWindow(sTempPos);
+        pos[0] = sTempPos[0] + sTempShift[0];
+        pos[1] = sTempPos[1] + sTempShift[1];
+    }
+
+    private static void getPagedViewScrollShift(View child, int[] shift) {
+        ViewParent parent = child.getParent();
+        if (parent instanceof PagedView) {
+            View parentView = (View) parent;
+            child.getLocationInWindow(sTempPos);
+            shift[0] = parentView.getPaddingLeft() - sTempPos[0];
+            shift[1] = -(int) child.getTranslationY();
+        } else if (parent instanceof View) {
+            getPagedViewScrollShift((View) parent, shift);
+        } else {
+            shift[0] = shift[1] = 0;
+        }
+    }
+}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index a9134e1..1890af4 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -18,13 +18,13 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.support.v4.widget.AutoScrollHelper;
 import android.text.InputType;
@@ -41,6 +41,7 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateInterpolator;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
@@ -70,7 +71,11 @@
     static final int STATE_ANIMATING = 1;
     static final int STATE_OPEN = 2;
 
+    private static final int CLOSE_FOLDER_DELAY_MS = 150;
+
     private int mExpandDuration;
+    private int mMaterialExpandDuration;
+    private int mMaterialExpandStagger;
     protected CellLayout mContent;
     private ScrollView mScrollView;
     private final LayoutInflater mInflater;
@@ -85,10 +90,10 @@
     private int mMaxCountY;
     private int mMaxNumItems;
     private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
-    private Drawable mIconDrawable;
     boolean mItemsInvalidated = false;
     private ShortcutInfo mCurrentDragInfo;
     private View mCurrentDragView;
+    private boolean mIsExternalDrag;
     boolean mSuppressOnAdd = false;
     private int[] mTargetCell = new int[2];
     private int[] mPreviousTargetCell = new int[2];
@@ -111,9 +116,7 @@
     private static String sDefaultFolderName;
     private static String sHintText;
 
-    private int DRAG_MODE_NONE = 0;
-    private int DRAG_MODE_REORDER = 1;
-    private int mDragMode = DRAG_MODE_NONE;
+    private FocusIndicatorView mFocusIndicatorHandler;
 
     // We avoid measuring the scroll view with a 0 width or height, as this
     // results in CellLayout being measured as UNSPECIFIED, which it does
@@ -156,7 +159,9 @@
         mInputMethodManager = (InputMethodManager)
                 getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
-        mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration);
+        mExpandDuration = res.getInteger(R.integer.config_folderExpandDuration);
+        mMaterialExpandDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
+        mMaterialExpandStagger = res.getInteger(R.integer.config_materialFolderExpandStagger);
 
         if (sDefaultFolderName == null) {
             sDefaultFolderName = res.getString(R.string.folder_name);
@@ -177,6 +182,11 @@
         mScrollView = (ScrollView) findViewById(R.id.scroll_view);
         mContent = (CellLayout) findViewById(R.id.folder_content);
 
+        mFocusIndicatorHandler = new FocusIndicatorView(getContext());
+        mContent.addView(mFocusIndicatorHandler, 0);
+        mFocusIndicatorHandler.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
+        mFocusIndicatorHandler.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
+
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
 
@@ -238,11 +248,7 @@
                 return false;
             }
 
-            mLauncher.getLauncherClings().dismissFolderCling(null);
-
-            mLauncher.getWorkspace().onDragStartedWithItem(v);
             mLauncher.getWorkspace().beginDragShared(v, this);
-            mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
 
             mCurrentDragInfo = item;
             mEmptyCell[0] = item.cellX;
@@ -303,8 +309,8 @@
         return mFolderName;
     }
 
-    public Drawable getDragDrawable() {
-        return mIconDrawable;
+    public CellLayout getContent() {
+        return mContent;
     }
 
     /**
@@ -381,7 +387,7 @@
         int count = 0;
         for (int i = 0; i < children.size(); i++) {
             ShortcutInfo child = (ShortcutInfo) children.get(i);
-            if (!createAndAddShortcut(child)) {
+            if (createAndAddShortcut(child) == null) {
                 overflow.add(child);
             } else {
                 count++;
@@ -391,7 +397,7 @@
         // We rearrange the items in case there are any empty gaps
         setupContentForNumItems(count);
 
-        // If our folder has too many items we prune them from the list. This is an issue 
+        // If our folder has too many items we prune them from the list. This is an issue
         // when upgrading from the old Folders implementation which could contain an unlimited
         // number of items.
         for (ShortcutInfo item: overflow) {
@@ -443,18 +449,93 @@
         mState = STATE_SMALL;
     }
 
+    private void prepareReveal() {
+        setScaleX(1f);
+        setScaleY(1f);
+        setAlpha(1f);
+        mState = STATE_SMALL;
+    }
+
     public void animateOpen() {
-        positionAndSizeAsIcon();
-
         if (!(getParent() instanceof DragLayer)) return;
-        centerAboutIcon();
-        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
-        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
-        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
-        final ObjectAnimator oa =
-            LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
-        oa.addListener(new AnimatorListenerAdapter() {
+        Animator openFolderAnim = null;
+        final Runnable onCompleteRunnable;
+        if (!Utilities.isLmpOrAbove()) {
+            positionAndSizeAsIcon();
+            centerAboutIcon();
+
+            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
+            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+            final ObjectAnimator oa =
+                LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+            oa.setDuration(mExpandDuration);
+            openFolderAnim = oa;
+
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+            onCompleteRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    setLayerType(LAYER_TYPE_NONE, null);
+                }
+            };
+        } else {
+            prepareReveal();
+            centerAboutIcon();
+
+            int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+            int height = getFolderHeight();
+
+            float transX = - 0.075f * (width / 2 - getPivotX());
+            float transY = - 0.075f * (height / 2 - getPivotY());
+            setTranslationX(transX);
+            setTranslationY(transY);
+            PropertyValuesHolder tx = PropertyValuesHolder.ofFloat("translationX", transX, 0);
+            PropertyValuesHolder ty = PropertyValuesHolder.ofFloat("translationY", transY, 0);
+
+            int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
+            int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
+            float radius = (float) Math.sqrt(rx * rx + ry * ry);
+            AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
+            Animator reveal = LauncherAnimUtils.createCircularReveal(this, (int) getPivotX(),
+                    (int) getPivotY(), 0, radius);
+            reveal.setDuration(mMaterialExpandDuration);
+            reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+
+            mContent.setAlpha(0f);
+            Animator iconsAlpha = LauncherAnimUtils.ofFloat(mContent, "alpha", 0f, 1f);
+            iconsAlpha.setDuration(mMaterialExpandDuration);
+            iconsAlpha.setStartDelay(mMaterialExpandStagger);
+            iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+
+            mFolderName.setAlpha(0f);
+            Animator textAlpha = LauncherAnimUtils.ofFloat(mFolderName, "alpha", 0f, 1f);
+            textAlpha.setDuration(mMaterialExpandDuration);
+            textAlpha.setStartDelay(mMaterialExpandStagger);
+            textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+
+            Animator drift = LauncherAnimUtils.ofPropertyValuesHolder(this, tx, ty);
+            drift.setDuration(mMaterialExpandDuration);
+            drift.setStartDelay(mMaterialExpandStagger);
+            drift.setInterpolator(new LogDecelerateInterpolator(60, 0));
+
+            anim.play(drift);
+            anim.play(iconsAlpha);
+            anim.play(textAlpha);
+            anim.play(reveal);
+
+            openFolderAnim = anim;
+
+            mContent.setLayerType(LAYER_TYPE_HARDWARE, null);
+            onCompleteRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    mContent.setLayerType(LAYER_TYPE_NONE, null);
+                }
+            };
+        }
+        openFolderAnim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
                 sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
@@ -465,19 +546,32 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mState = STATE_OPEN;
-                setLayerType(LAYER_TYPE_NONE, null);
-                Cling cling = mLauncher.getLauncherClings().showFoldersCling();
-                if (cling != null) {
-                    cling.bringScrimToFront();
-                    bringToFront();
-                    cling.bringToFront();
+
+                if (onCompleteRunnable != null) {
+                    onCompleteRunnable.run();
                 }
+
                 setFocusOnFirstChild();
             }
         });
-        oa.setDuration(mExpandDuration);
-        setLayerType(LAYER_TYPE_HARDWARE, null);
-        oa.start();
+        openFolderAnim.start();
+
+        // Make sure the folder picks up the last drag move even if the finger doesn't move.
+        if (mDragController.isDragging()) {
+            mDragController.forceTouchMove();
+        }
+    }
+
+    public void beginExternalDrag(ShortcutInfo item) {
+        setupContentForNumItems(getItemCount() + 1);
+        findAndSetEmptyCells(item);
+
+        mCurrentDragInfo = item;
+        mEmptyCell[0] = item.cellX;
+        mEmptyCell[1] = item.cellY;
+        mIsExternalDrag = true;
+
+        mDragInProgress = true;
     }
 
     private void sendCustomAccessibilityEvent(int type, String text) {
@@ -544,28 +638,23 @@
         }
     }
 
-    protected boolean createAndAddShortcut(ShortcutInfo item) {
+    protected View createAndAddShortcut(ShortcutInfo item) {
         final BubbleTextView textView =
-            (BubbleTextView) mInflater.inflate(R.layout.application, this, false);
-        textView.setCompoundDrawables(null,
-                Utilities.createIconDrawable(item.getIcon(mIconCache)), null, null);
-        textView.setText(item.title);
-        textView.setTag(item);
-        textView.setTextColor(getResources().getColor(R.color.folder_items_text_color));
-        textView.setShadowsEnabled(false);
-        textView.setGlowColor(getResources().getColor(R.color.folder_items_glow_color));
+            (BubbleTextView) mInflater.inflate(R.layout.folder_application, this, false);
+        textView.applyFromShortcutInfo(item, mIconCache, false);
 
         textView.setOnClickListener(this);
         textView.setOnLongClickListener(this);
+        textView.setOnFocusChangeListener(mFocusIndicatorHandler);
 
         // We need to check here to verify that the given item's location isn't already occupied
         // by another item.
         if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0
                 || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) {
-            // This shouldn't happen, log it. 
+            // This shouldn't happen, log it.
             Log.e(TAG, "Folder order not properly persisted during bind");
             if (!findAndSetEmptyCells(item)) {
-                return false;
+                return null;
             }
         }
 
@@ -574,7 +663,7 @@
         boolean insert = false;
         textView.setOnKeyListener(new FolderKeyEventListener());
         mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
-        return true;
+        return textView;
     }
 
     public void onDragEnter(DragObject d) {
@@ -678,9 +767,6 @@
                 mReorderAlarm.setAlarm(REORDER_DELAY);
                 mPreviousTargetCell[0] = mTargetCell[0];
                 mPreviousTargetCell[1] = mTargetCell[1];
-                mDragMode = DRAG_MODE_REORDER;
-            } else {
-                mDragMode = DRAG_MODE_NONE;
             }
         }
     }
@@ -723,6 +809,7 @@
         mCurrentDragView = null;
         mSuppressOnAdd = false;
         mRearrangeOnClose = true;
+        mIsExternalDrag = false;
     }
 
     public void onDragExit(DragObject d) {
@@ -735,7 +822,6 @@
             mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
         }
         mReorderAlarm.cancelAlarm();
-        mDragMode = DRAG_MODE_NONE;
     }
 
     public void onDropCompleted(final View target, final DragObject d,
@@ -756,7 +842,7 @@
                 success && (!beingCalledAfterUninstall || mUninstallSuccessful);
 
         if (successfulDrop) {
-            if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
+            if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) {
                 replaceFolderWithFinalItem();
             }
         } else {
@@ -775,12 +861,6 @@
             }
         }
 
-        // This is kind of hacky, but in general, dropping on the workspace handles removing
-        // the extra screen, but dropping elsewhere (back to self, or onto delete) doesn't.
-        if (target != mLauncher.getWorkspace()) {
-            mLauncher.getWorkspace().removeExtraEmptyScreen(true, null);
-        }
-
         mDeleteFolderOnDropCompleted = false;
         mDragInProgress = false;
         mItemAddedBackToSelfViaIcon = false;
@@ -1152,34 +1232,71 @@
     }
 
     public void onDrop(DragObject d) {
-        ShortcutInfo item;
-        if (d.dragInfo instanceof AppInfo) {
-            // Came from all apps -- make a copy
-            item = ((AppInfo) d.dragInfo).makeShortcut();
-            item.spanX = 1;
-            item.spanY = 1;
-        } else {
-            item = (ShortcutInfo) d.dragInfo;
+        Runnable cleanUpRunnable = null;
+
+        // If we are coming from All Apps space, we defer removing the extra empty screen
+        // until the folder closes
+        if (d.dragSource != mLauncher.getWorkspace() && !(d.dragSource instanceof Folder)) {
+            cleanUpRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    mLauncher.exitSpringLoadedDragModeDelayed(true,
+                            Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT,
+                            null);
+                }
+            };
         }
-        // Dragged from self onto self, currently this is the only path possible, however
-        // we keep this as a distinct code path.
-        if (item == mCurrentDragInfo) {
-            ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
-            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
+
+        View currentDragView;
+        ShortcutInfo si = mCurrentDragInfo;
+        if (mIsExternalDrag) {
+            si.cellX = mEmptyCell[0];
+            si.cellY = mEmptyCell[1];
+
+            // Actually move the item in the database if it was an external drag. Call this
+            // before creating the view, so that ShortcutInfo is updated appropriately.
+            LauncherModel.addOrMoveItemInDatabase(
+                    mLauncher, si, mInfo.id, 0, si.cellX, si.cellY);
+
+            // We only need to update the locations if it doesn't get handled in #onDropCompleted.
+            if (d.dragSource != this) {
+                updateItemLocationsInDatabaseBatch();
+            }
+            mIsExternalDrag = false;
+
+            currentDragView = createAndAddShortcut(si);
+        } else {
+            currentDragView = mCurrentDragView;
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams();
             si.cellX = lp.cellX = mEmptyCell[0];
             si.cellX = lp.cellY = mEmptyCell[1];
-            mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
-            if (d.dragView.hasDrawn()) {
-                mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
-            } else {
-                d.deferDragViewCleanupPostAnimation = false;
-                mCurrentDragView.setVisibility(VISIBLE);
-            }
-            mItemsInvalidated = true;
-            setupContentDimensions(getItemCount());
-            mSuppressOnAdd = true;
+            mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true);
         }
-        mInfo.add(item);
+
+        if (d.dragView.hasDrawn()) {
+
+            // Temporarily reset the scale such that the animation target gets calculated correctly.
+            float scaleX = getScaleX();
+            float scaleY = getScaleY();
+            setScaleX(1.0f);
+            setScaleY(1.0f);
+            mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, currentDragView,
+                    cleanUpRunnable, null);
+            setScaleX(scaleX);
+            setScaleY(scaleY);
+        } else {
+            d.deferDragViewCleanupPostAnimation = false;
+            currentDragView.setVisibility(VISIBLE);
+        }
+        mItemsInvalidated = true;
+        setupContentDimensions(getItemCount());
+
+        // Temporarily suppress the listener, as we did all the work already here.
+        mSuppressOnAdd = true;
+        mInfo.add(si);
+        mSuppressOnAdd = false;
+        // Clear the drag info, as it is no longer being dragged.
+        mCurrentDragInfo = null;
     }
 
     // This is used so the item doesn't immediately appear in the folder when added. In one case
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 644db47..a359f11 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -33,6 +33,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
@@ -70,15 +71,21 @@
     private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
 
     // The amount of vertical spread between items in the stack [0...1]
-    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.24f;
+    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
 
     // Flag as to whether or not to draw an outer ring. Currently none is designed.
     public static final boolean HAS_OUTER_RING = true;
 
+    // Flag whether the folder should open itself when an item is dragged over is enabled.
+    public static final boolean SPRING_LOADING_ENABLED = true;
+
     // The degree to which the item in the back of the stack is scaled [0...1]
     // (0 means it's not scaled at all, 1 means it's scaled to nothing)
     private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
 
+    // Delay when drag enters until the folder opens, in miliseconds.
+    private static final int ON_OPEN_DELAY = 800;
+
     public static Drawable sSharedFolderLeaveBehind = null;
 
     private ImageView mPreviewBackground;
@@ -99,10 +106,15 @@
     boolean mAnimating = false;
     private Rect mOldBounds = new Rect();
 
+    private float mSlop;
+
     private PreviewItemDrawingParams mParams = new PreviewItemDrawingParams(0, 0, 0, 0);
     private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
     private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
 
+    private Alarm mOpenAlarm = new Alarm();
+    private ItemInfo mDragInfo;
+
     public FolderIcon(Context context, AttributeSet attrs) {
         super(context, attrs);
         init();
@@ -121,7 +133,7 @@
         final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
         final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
         final Workspace workspace = (Workspace) cellLayout.getParent();
-        return !workspace.isSmall();
+        return !workspace.workspaceInModalState();
     }
 
     static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@@ -166,6 +178,7 @@
         icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
         folderInfo.addListener(icon);
 
+        icon.setOnFocusChangeListener(launcher.mFocusHandler);
         return icon;
     }
 
@@ -299,7 +312,7 @@
         }
     }
 
-    Folder getFolder() {
+    public Folder getFolder() {
         return mFolder;
     }
 
@@ -331,17 +344,44 @@
         mFolderRingAnimator.setCellLayout(layout);
         mFolderRingAnimator.animateToAcceptState();
         layout.showFolderAccept(mFolderRingAnimator);
+        mOpenAlarm.setOnAlarmListener(mOnOpenListener);
+        if (SPRING_LOADING_ENABLED &&
+                ((dragInfo instanceof AppInfo) || (dragInfo instanceof ShortcutInfo))) {
+            // TODO: we currently don't support spring-loading for PendingAddShortcutInfos even
+            // though widget-style shortcuts can be added to folders. The issue is that we need
+            // to deal with configuration activities which are currently handled in
+            // Workspace#onDropExternal.
+            mOpenAlarm.setAlarm(ON_OPEN_DELAY);
+        }
+        mDragInfo = (ItemInfo) dragInfo;
     }
 
     public void onDragOver(Object dragInfo) {
     }
 
+    OnAlarmListener mOnOpenListener = new OnAlarmListener() {
+        public void onAlarm(Alarm alarm) {
+            ShortcutInfo item;
+            if (mDragInfo instanceof AppInfo) {
+                // Came from all apps -- make a copy.
+                item = ((AppInfo) mDragInfo).makeShortcut();
+                item.spanX = 1;
+                item.spanY = 1;
+            } else {
+                // ShortcutInfo
+                item = (ShortcutInfo) mDragInfo;
+            }
+            mFolder.beginExternalDrag(item);
+            mLauncher.openFolder(FolderIcon.this);
+        }
+    };
+
     public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
             final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
             float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
 
         // These correspond two the drawable and view that the icon was dropped _onto_
-        Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
+        Drawable animateDrawable = getTopDrawable((TextView) destView);
         computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
                 destView.getMeasuredWidth());
 
@@ -355,8 +395,8 @@
     }
 
     public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) {
-        Drawable animateDrawable = ((TextView) finalView).getCompoundDrawables()[1];
-        computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), 
+        Drawable animateDrawable = getTopDrawable((TextView) finalView);
+        computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
                 finalView.getMeasuredWidth());
 
         // This will animate the first item from it's position as an icon into its
@@ -371,6 +411,7 @@
 
     public void onDragExit() {
         mFolderRingAnimator.animateToNaturalState();
+        mOpenAlarm.cancelAlarm();
     }
 
     private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
@@ -461,6 +502,7 @@
             int adjustedAvailableSpace = (int) ((mAvailableSpaceInPreview / 2) * (1 + 0.8f));
 
             int unscaledHeight = (int) (mIntrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR));
+
             mBaselineIconScale = (1.0f * adjustedAvailableSpace / unscaledHeight);
 
             mBaselineIconSize = (int) (mIntrinsicIconSize * mBaselineIconScale);
@@ -515,7 +557,7 @@
         // We want to imagine our coordinates from the bottom left, growing up and to the
         // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
         float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection) + getPaddingTop();
-        float transX = offset + scaleOffsetCorrection;
+        float transX = (mAvailableSpaceInPreview - scaledSize) / 2;
         float totalScale = mBaselineIconScale * scale;
         final int overlayAlpha = (int) (80 * (1 - r));
 
@@ -539,10 +581,18 @@
         if (d != null) {
             mOldBounds.set(d.getBounds());
             d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
-            d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255),
-                    PorterDuff.Mode.SRC_ATOP);
-            d.draw(canvas);
-            d.clearColorFilter();
+            if (d instanceof FastBitmapDrawable) {
+                FastBitmapDrawable fd = (FastBitmapDrawable) d;
+                int oldBrightness = fd.getBrightness();
+                fd.setBrightness(params.overlayAlpha);
+                d.draw(canvas);
+                fd.setBrightness(oldBrightness);
+            } else {
+                d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255),
+                        PorterDuff.Mode.SRC_ATOP);
+                d.draw(canvas);
+                d.clearColorFilter();
+            }
             d.setBounds(mOldBounds);
         }
         canvas.restore();
@@ -564,7 +614,7 @@
             computePreviewDrawingParams(mAnimParams.drawable);
         } else {
             v = (TextView) items.get(0);
-            d = v.getCompoundDrawables()[1];
+            d = getTopDrawable(v);
             computePreviewDrawingParams(d);
         }
 
@@ -573,7 +623,7 @@
             for (int i = nItemsInPreview - 1; i >= 0; i--) {
                 v = (TextView) items.get(i);
                 if (!mHiddenItems.contains(v.getTag())) {
-                    d = v.getCompoundDrawables()[1];
+                    d = getTopDrawable(v);
                     mParams = computePreviewItemDrawingParams(i, mParams);
                     mParams.drawable = d;
                     drawPreviewItem(canvas, mParams);
@@ -584,6 +634,11 @@
         }
     }
 
+    private Drawable getTopDrawable(TextView v) {
+        Drawable d = v.getCompoundDrawables()[1];
+        return (d instanceof PreloadIconDrawable) ? ((PreloadIconDrawable) d).mIcon : d;
+    }
+
     private void animateFirstItem(final Drawable d, int duration, final boolean reverse,
             final Runnable onCompleteRunnable) {
         final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
@@ -672,11 +727,22 @@
             case MotionEvent.ACTION_UP:
                 mLongPressHelper.cancelLongPress();
                 break;
+            case MotionEvent.ACTION_MOVE:
+                if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
+                    mLongPressHelper.cancelLongPress();
+                }
+                break;
         }
         return result;
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+    }
+
+    @Override
     public void cancelLongPress() {
         super.cancelLongPress();
 
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index d45e4e4..85a792f 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -17,13 +17,17 @@
 package com.android.launcher3;
 
 import android.content.ContentValues;
+import android.content.Context;
+
+import com.android.launcher3.compat.UserHandleCompat;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Represents a folder containing shortcuts or apps.
  */
-class FolderInfo extends ItemInfo {
+public class FolderInfo extends ItemInfo {
 
     /**
      * Whether this folder has been opened
@@ -39,6 +43,7 @@
 
     FolderInfo() {
         itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
+        user = UserHandleCompat.myUserHandle();
     }
 
     /**
@@ -75,8 +80,8 @@
     }
 
     @Override
-    void onAddToDatabase(ContentValues values) {
-        super.onAddToDatabase(values);
+    void onAddToDatabase(Context context, ContentValues values) {
+        super.onAddToDatabase(context, values);
         values.put(LauncherSettings.Favorites.TITLE, title.toString());
     }
 
@@ -114,6 +119,6 @@
         return "FolderInfo(id=" + this.id + " type=" + this.itemType
                 + " container=" + this.container + " screen=" + screenId
                 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
-                + " spanY=" + spanY + " dropPos=" + dropPos + ")";
+                + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + ")";
     }
 }
diff --git a/src/com/android/launcher3/HideFromAccessibilityHelper.java b/src/com/android/launcher3/HideFromAccessibilityHelper.java
deleted file mode 100644
index 75cbb1b..0000000
--- a/src/com/android/launcher3/HideFromAccessibilityHelper.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.OnHierarchyChangeListener;
-
-import java.util.HashMap;
-
-public class HideFromAccessibilityHelper implements OnHierarchyChangeListener {
-    private HashMap<View, Integer> mPreviousValues;
-    boolean mHide;
-    boolean mOnlyAllApps;
-
-    public HideFromAccessibilityHelper() {
-        mPreviousValues = new HashMap<View, Integer>();
-        mHide = false;
-    }
-
-    public void setImportantForAccessibilityToNo(View v, boolean onlyAllApps) {
-        mOnlyAllApps = onlyAllApps;
-        setImportantForAccessibilityToNoHelper(v);
-        mHide = true;
-    }
-
-    private void setImportantForAccessibilityToNoHelper(View v) {
-        mPreviousValues.put(v, v.getImportantForAccessibility());
-        v.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
-
-        // Call method on children recursively
-        if (v instanceof ViewGroup) {
-            ViewGroup vg = (ViewGroup) v;
-            vg.setOnHierarchyChangeListener(this);
-            for (int i = 0; i < vg.getChildCount(); i++) {
-                View child = vg.getChildAt(i);
-
-                if (includeView(child)) {
-                    setImportantForAccessibilityToNoHelper(child);
-                }
-            }
-        }
-    }
-
-    public void restoreImportantForAccessibility(View v) {
-        if (mHide) {
-            restoreImportantForAccessibilityHelper(v);
-        }
-        mHide = false;
-    }
-
-    private void restoreImportantForAccessibilityHelper(View v) {
-        Integer important = mPreviousValues.get(v);
-        v.setImportantForAccessibility(important);
-        mPreviousValues.remove(v);
-
-        // Call method on children recursively
-        if (v instanceof ViewGroup) {
-            ViewGroup vg = (ViewGroup) v;
-
-            // We assume if a class implements OnHierarchyChangeListener, it listens
-            // to changes to any of its children (happens to be the case in Launcher)
-            if (vg instanceof OnHierarchyChangeListener) {
-                vg.setOnHierarchyChangeListener((OnHierarchyChangeListener) vg);
-            } else {
-                vg.setOnHierarchyChangeListener(null);
-            }
-            for (int i = 0; i < vg.getChildCount(); i++) {
-                View child = vg.getChildAt(i);
-                if (includeView(child)) {
-                    restoreImportantForAccessibilityHelper(child);
-                }
-            }
-        }
-    }
-
-    public void onChildViewAdded(View parent, View child) {
-        if (mHide && includeView(child)) {
-            setImportantForAccessibilityToNoHelper(child);
-        }
-    }
-
-    public void onChildViewRemoved(View parent, View child) {
-        if (mHide && includeView(child)) {
-            restoreImportantForAccessibilityHelper(child);
-        }
-    }
-
-    private boolean includeView(View v) {
-        return !hasAncestorOfType(v, Cling.class) &&
-                (!mOnlyAllApps || hasAncestorOfType(v, AppsCustomizeTabHost.class));
-    }
-
-    private boolean hasAncestorOfType(View v, Class c) {
-        return v != null &&
-                (v.getClass().equals(c) ||
-                 (v.getParent() instanceof ViewGroup &&
-                  hasAncestorOfType((ViewGroup) v.getParent(), c)));
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/HolographicOutlineHelper.java b/src/com/android/launcher3/HolographicOutlineHelper.java
index d7b960a..b1e0e68 100644
--- a/src/com/android/launcher3/HolographicOutlineHelper.java
+++ b/src/com/android/launcher3/HolographicOutlineHelper.java
@@ -20,48 +20,49 @@
 import android.graphics.Bitmap;
 import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
 
 public class HolographicOutlineHelper {
-    private final Paint mHolographicPaint = new Paint();
+
+    private static final Rect sTempRect = new Rect();
+
+    private final Canvas mCanvas = new Canvas();
+    private final Paint mDrawPaint = new Paint();
     private final Paint mBlurPaint = new Paint();
     private final Paint mErasePaint = new Paint();
 
-    public int mMaxOuterBlurRadius;
-    public int mMinOuterBlurRadius;
+    private final BlurMaskFilter mMediumOuterBlurMaskFilter;
+    private final BlurMaskFilter mThinOuterBlurMaskFilter;
+    private final BlurMaskFilter mMediumInnerBlurMaskFilter;
 
-    private BlurMaskFilter mExtraThickOuterBlurMaskFilter;
-    private BlurMaskFilter mThickOuterBlurMaskFilter;
-    private BlurMaskFilter mMediumOuterBlurMaskFilter;
-    private BlurMaskFilter mThinOuterBlurMaskFilter;
-    private BlurMaskFilter mThickInnerBlurMaskFilter;
-    private BlurMaskFilter mExtraThickInnerBlurMaskFilter;
-    private BlurMaskFilter mMediumInnerBlurMaskFilter;
+    private final BlurMaskFilter mShaowBlurMaskFilter;
+    private final int mShadowOffset;
 
-    private static final int THICK = 0;
-    private static final int MEDIUM = 1;
-    private static final int EXTRA_THICK = 2;
+    /**
+     * Padding used when creating shadow bitmap;
+     */
+    final int shadowBitmapPadding;
 
     static HolographicOutlineHelper INSTANCE;
 
     private HolographicOutlineHelper(Context context) {
         final float scale = LauncherAppState.getInstance().getScreenDensity();
 
-        mMinOuterBlurRadius = (int) (scale * 1.0f);
-        mMaxOuterBlurRadius = (int) (scale * 12.0f);
-
-        mExtraThickOuterBlurMaskFilter = new BlurMaskFilter(scale * 12.0f, BlurMaskFilter.Blur.OUTER);
-        mThickOuterBlurMaskFilter = new BlurMaskFilter(scale * 6.0f, BlurMaskFilter.Blur.OUTER);
         mMediumOuterBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.OUTER);
         mThinOuterBlurMaskFilter = new BlurMaskFilter(scale * 1.0f, BlurMaskFilter.Blur.OUTER);
-        mExtraThickInnerBlurMaskFilter = new BlurMaskFilter(scale * 6.0f, BlurMaskFilter.Blur.NORMAL);
-        mThickInnerBlurMaskFilter = new BlurMaskFilter(scale * 4.0f, BlurMaskFilter.Blur.NORMAL);
         mMediumInnerBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.NORMAL);
 
-        mHolographicPaint.setFilterBitmap(true);
-        mHolographicPaint.setAntiAlias(true);
+        mShaowBlurMaskFilter = new BlurMaskFilter(scale * 4.0f, BlurMaskFilter.Blur.NORMAL);
+        mShadowOffset = (int) (scale * 2.0f);
+        shadowBitmapPadding = (int) (scale * 4.0f);
+
+        mDrawPaint.setFilterBitmap(true);
+        mDrawPaint.setAntiAlias(true);
         mBlurPaint.setFilterBitmap(true);
         mBlurPaint.setAntiAlias(true);
         mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
@@ -77,37 +78,15 @@
     }
 
     /**
-     * Returns the interpolated holographic highlight alpha for the effect we want when scrolling
-     * pages.
-     */
-    public static float highlightAlphaInterpolator(float r) {
-        float maxAlpha = 0.6f;
-        return (float) Math.pow(maxAlpha * (1.0f - r), 1.5f);
-    }
-
-    /**
-     * Returns the interpolated view alpha for the effect we want when scrolling pages.
-     */
-    public static float viewAlphaInterpolator(float r) {
-        final float pivot = 0.95f;
-        if (r < pivot) {
-            return (float) Math.pow(r / pivot, 1.5f);
-        } else {
-            return 1.0f;
-        }
-    }
-
-    /**
      * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
      * bitmap.
      */
     void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor, int thickness) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, true,
-                thickness);
+            int outlineColor) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, true);
     }
     void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor, boolean clipAlpha, int thickness) {
+            int outlineColor, boolean clipAlpha) {
 
         // We start by removing most of the alpha channel so as to ignore shadows, and
         // other types of partial transparency when defining the shape of the object
@@ -127,50 +106,18 @@
         Bitmap glowShape = srcDst.extractAlpha();
 
         // calculate the outer blur first
-        BlurMaskFilter outerBlurMaskFilter;
-        switch (thickness) {
-            case EXTRA_THICK:
-                outerBlurMaskFilter = mExtraThickOuterBlurMaskFilter;
-                break;
-            case THICK:
-                outerBlurMaskFilter = mThickOuterBlurMaskFilter;
-                break;
-            case MEDIUM:
-                outerBlurMaskFilter = mMediumOuterBlurMaskFilter;
-                break;
-            default:
-                throw new RuntimeException("Invalid blur thickness");
-        }
-        mBlurPaint.setMaskFilter(outerBlurMaskFilter);
+        mBlurPaint.setMaskFilter(mMediumOuterBlurMaskFilter);
         int[] outerBlurOffset = new int[2];
         Bitmap thickOuterBlur = glowShape.extractAlpha(mBlurPaint, outerBlurOffset);
-        if (thickness == EXTRA_THICK) {
-            mBlurPaint.setMaskFilter(mMediumOuterBlurMaskFilter);
-        } else {
-            mBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter);
-        }
 
+        mBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter);
         int[] brightOutlineOffset = new int[2];
         Bitmap brightOutline = glowShape.extractAlpha(mBlurPaint, brightOutlineOffset);
 
         // calculate the inner blur
         srcDstCanvas.setBitmap(glowShape);
         srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
-        BlurMaskFilter innerBlurMaskFilter;
-        switch (thickness) {
-            case EXTRA_THICK:
-                innerBlurMaskFilter = mExtraThickInnerBlurMaskFilter;
-                break;
-            case THICK:
-                innerBlurMaskFilter = mThickInnerBlurMaskFilter;
-                break;
-            case MEDIUM:
-                innerBlurMaskFilter = mMediumInnerBlurMaskFilter;
-                break;
-            default:
-                throw new RuntimeException("Invalid blur thickness");
-        }
-        mBlurPaint.setMaskFilter(innerBlurMaskFilter);
+        mBlurPaint.setMaskFilter(mMediumInnerBlurMaskFilter);
         int[] thickInnerBlurOffset = new int[2];
         Bitmap thickInnerBlur = glowShape.extractAlpha(mBlurPaint, thickInnerBlurOffset);
 
@@ -186,16 +133,16 @@
         // draw the inner and outer blur
         srcDstCanvas.setBitmap(srcDst);
         srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
-        mHolographicPaint.setColor(color);
+        mDrawPaint.setColor(color);
         srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
-                mHolographicPaint);
+                mDrawPaint);
         srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
-                mHolographicPaint);
+                mDrawPaint);
 
         // draw the bright outline
-        mHolographicPaint.setColor(outlineColor);
+        mDrawPaint.setColor(outlineColor);
         srcDstCanvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1],
-                mHolographicPaint);
+                mDrawPaint);
 
         // cleanup
         srcDstCanvas.setBitmap(null);
@@ -205,25 +152,52 @@
         glowShape.recycle();
     }
 
-    void applyExtraThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, EXTRA_THICK);
-    }
+    Bitmap createMediumDropShadow(BubbleTextView view) {
+        final Bitmap result = Bitmap.createBitmap(
+                view.getWidth() + shadowBitmapPadding + shadowBitmapPadding,
+                view.getHeight() + shadowBitmapPadding + shadowBitmapPadding + mShadowOffset,
+                Bitmap.Config.ARGB_8888);
 
-    void applyThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, THICK);
-    }
+        mCanvas.setBitmap(result);
 
-    void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor, boolean clipAlpha) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, clipAlpha,
-                MEDIUM);
-    }
+        final Rect clipRect = sTempRect;
+        view.getDrawingRect(sTempRect);
+        // adjust the clip rect so that we don't include the text label
+        clipRect.bottom = view.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V
+                + view.getLayout().getLineTop(0);
 
-    void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
-            int outlineColor) {
-        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, MEDIUM);
-    }
+        // Draw the View into the bitmap.
+        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
+        // they set scrollX and scrollY to large values to achieve centered text
+        mCanvas.save();
+        mCanvas.scale(view.getScaleX(), view.getScaleY(),
+                view.getWidth() / 2 + shadowBitmapPadding,
+                view.getHeight() / 2 + shadowBitmapPadding);
+        mCanvas.translate(-view.getScrollX() + shadowBitmapPadding,
+                -view.getScrollY() + shadowBitmapPadding);
+        mCanvas.clipRect(clipRect, Op.REPLACE);
+        view.draw(mCanvas);
+        mCanvas.restore();
 
+        int[] blurOffst = new int[2];
+        mBlurPaint.setMaskFilter(mShaowBlurMaskFilter);
+        Bitmap blurBitmap = result.extractAlpha(mBlurPaint, blurOffst);
+
+        mCanvas.save();
+        mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+        mCanvas.translate(blurOffst[0], blurOffst[1]);
+
+        mDrawPaint.setColor(Color.BLACK);
+        mDrawPaint.setAlpha(30);
+        mCanvas.drawBitmap(blurBitmap, 0, 0, mDrawPaint);
+
+        mDrawPaint.setAlpha(60);
+        mCanvas.drawBitmap(blurBitmap, 0, mShadowOffset, mDrawPaint);
+        mCanvas.restore();
+
+        mCanvas.setBitmap(null);
+        blurBitmap.recycle();
+
+        return result;
+    }
 }
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 59d60e3..b08272f 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -64,7 +64,6 @@
 
     public void setup(Launcher launcher) {
         mLauncher = launcher;
-        setOnKeyListener(new HotseatIconKeyEventListener());
     }
 
     CellLayout getLayout() {
@@ -150,21 +149,18 @@
             TextView allAppsButton = (TextView)
                     inflater.inflate(R.layout.all_apps_button, mContent, false);
             Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
+
             Utilities.resizeIconDrawable(d);
             allAppsButton.setCompoundDrawables(null, d, null, null);
 
             allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
+            allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
             if (mLauncher != null) {
                 allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+                mLauncher.setAllAppsButton(allAppsButton);
+                allAppsButton.setOnClickListener(mLauncher);
+                allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
             }
-            allAppsButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(android.view.View v) {
-                    if (mLauncher != null) {
-                        mLauncher.onClickAllAppsButton(v);
-                    }
-                }
-            });
 
             // Note: We do this to ensure that the hotseat is always laid out in the orientation of
             // the hotseat in order regardless of which orientation they were added
@@ -172,7 +168,7 @@
             int y = getCellYFromOrder(mAllAppsButtonRank);
             CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
             lp.canReorder = false;
-            mContent.addViewToCellLayout(allAppsButton, -1, 0, lp, true);
+            mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
         }
     }
 
@@ -180,7 +176,7 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // We don't want any clicks to go through to the hotseat unless the workspace is in
         // the normal state.
-        if (mLauncher.getWorkspace().isSmall()) {
+        if (mLauncher.getWorkspace().workspaceInModalState()) {
             return true;
         }
         return false;
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index a55fce0..bb71d77 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -21,14 +21,32 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
 
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map.Entry;
 
@@ -36,21 +54,52 @@
  * Cache of application icons.  Icons can be made from any thread.
  */
 public class IconCache {
-    @SuppressWarnings("unused")
+
     private static final String TAG = "Launcher.IconCache";
 
     private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
+    private static final String RESOURCE_FILE_PREFIX = "icon_";
+
+    // Empty class name is used for storing package default entry.
+    private static final String EMPTY_CLASS_NAME = ".";
+
+    private static final boolean DEBUG = false;
 
     private static class CacheEntry {
         public Bitmap icon;
-        public String title;
+        public CharSequence title;
+        public CharSequence contentDescription;
     }
 
-    private final Bitmap mDefaultIcon;
+    private static class CacheKey {
+        public ComponentName componentName;
+        public UserHandleCompat user;
+
+        CacheKey(ComponentName componentName, UserHandleCompat user) {
+            this.componentName = componentName;
+            this.user = user;
+        }
+
+        @Override
+        public int hashCode() {
+            return componentName.hashCode() + user.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            CacheKey other = (CacheKey) o;
+            return other.componentName.equals(componentName) && other.user.equals(user);
+        }
+    }
+
+    private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons =
+            new HashMap<UserHandleCompat, Bitmap>();
     private final Context mContext;
     private final PackageManager mPackageManager;
-    private final HashMap<ComponentName, CacheEntry> mCache =
-            new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
+    private final UserManagerCompat mUserManager;
+    private final LauncherAppsCompat mLauncherApps;
+    private final HashMap<CacheKey, CacheEntry> mCache =
+            new HashMap<CacheKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
     private int mIconDpi;
 
     public IconCache(Context context) {
@@ -59,10 +108,13 @@
 
         mContext = context;
         mPackageManager = context.getPackageManager();
+        mUserManager = UserManagerCompat.getInstance(mContext);
+        mLauncherApps = LauncherAppsCompat.getInstance(mContext);
         mIconDpi = activityManager.getLauncherLargeIconDensity();
 
         // need to set mIconDpi before getting default icon
-        mDefaultIcon = makeDefaultIcon();
+        UserHandleCompat myUser = UserHandleCompat.myUserHandle();
+        mDefaultIcons.put(myUser, makeDefaultIcon(myUser));
     }
 
     public Drawable getFullResDefaultActivityIcon() {
@@ -96,6 +148,10 @@
         return getFullResDefaultActivityIcon();
     }
 
+    public int getFullResIconDpi() {
+        return mIconDpi;
+    }
+
     public Drawable getFullResIcon(ResolveInfo info) {
         return getFullResIcon(info.activityInfo);
     }
@@ -115,11 +171,13 @@
                 return getFullResIcon(resources, iconId);
             }
         }
+
         return getFullResDefaultActivityIcon();
     }
 
-    private Bitmap makeDefaultIcon() {
-        Drawable d = getFullResDefaultActivityIcon();
+    private Bitmap makeDefaultIcon(UserHandleCompat user) {
+        Drawable unbadged = getFullResDefaultActivityIcon();
+        Drawable d = mUserManager.getBadgedDrawableForUser(unbadged, user);
         Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),
                 Math.max(d.getIntrinsicHeight(), 1),
                 Bitmap.Config.ARGB_8888);
@@ -133,9 +191,25 @@
     /**
      * Remove any records for the supplied ComponentName.
      */
-    public void remove(ComponentName componentName) {
+    public void remove(ComponentName componentName, UserHandleCompat user) {
         synchronized (mCache) {
-            mCache.remove(componentName);
+            mCache.remove(new CacheKey(componentName, user));
+        }
+    }
+
+    /**
+     * Remove any records for the supplied package name.
+     */
+    public void remove(String packageName, UserHandleCompat user) {
+        HashSet<CacheKey> forDeletion = new HashSet<CacheKey>();
+        for (CacheKey key: mCache.keySet()) {
+            if (key.componentName.getPackageName().equals(packageName)
+                    && key.user.equals(user)) {
+                forDeletion.add(key);
+            }
+        }
+        for (CacheKey condemned: forDeletion) {
+            mCache.remove(condemned);
         }
     }
 
@@ -153,10 +227,11 @@
      */
     public void flushInvalidIcons(DeviceProfile grid) {
         synchronized (mCache) {
-            Iterator<Entry<ComponentName, CacheEntry>> it = mCache.entrySet().iterator();
+            Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
             while (it.hasNext()) {
                 final CacheEntry e = it.next().getValue();
-                if (e.icon.getWidth() < grid.iconSizePx || e.icon.getHeight() < grid.iconSizePx) {
+                if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
+                        || e.icon.getHeight() < grid.iconSizePx)) {
                     it.remove();
                 }
             }
@@ -166,69 +241,183 @@
     /**
      * Fill in "application" with the icon and label for "info."
      */
-    public void getTitleAndIcon(AppInfo application, ResolveInfo info,
+    public void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
             HashMap<Object, CharSequence> labelCache) {
         synchronized (mCache) {
-            CacheEntry entry = cacheLocked(application.componentName, info, labelCache);
+            CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
+                    info.getUser(), false);
 
             application.title = entry.title;
             application.iconBitmap = entry.icon;
+            application.contentDescription = entry.contentDescription;
         }
     }
 
-    public Bitmap getIcon(Intent intent) {
-        synchronized (mCache) {
-            final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
-            ComponentName component = intent.getComponent();
+    public Bitmap getIcon(Intent intent, UserHandleCompat user) {
+        return getIcon(intent, null, user, true);
+    }
 
-            if (resolveInfo == null || component == null) {
-                return mDefaultIcon;
+    private Bitmap getIcon(Intent intent, String title, UserHandleCompat user, boolean usePkgIcon) {
+        synchronized (mCache) {
+            ComponentName component = intent.getComponent();
+            // null info means not installed, but if we have a component from the intent then
+            // we should still look in the cache for restored app icons.
+            if (component == null) {
+                return getDefaultIcon(user);
             }
 
-            CacheEntry entry = cacheLocked(component, resolveInfo, null);
+            LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
+            CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
+            if (title != null) {
+                entry.title = title;
+                entry.contentDescription = mUserManager.getBadgedLabelForUser(title, user);
+            }
             return entry.icon;
         }
     }
 
-    public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo,
+    /**
+     * Fill in "shortcutInfo" with the icon and label for "info."
+     */
+    public void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent, UserHandleCompat user,
+            boolean usePkgIcon) {
+        synchronized (mCache) {
+            ComponentName component = intent.getComponent();
+            // null info means not installed, but if we have a component from the intent then
+            // we should still look in the cache for restored app icons.
+            if (component == null) {
+                shortcutInfo.setIcon(getDefaultIcon(user));
+                shortcutInfo.title = "";
+                shortcutInfo.usingFallbackIcon = true;
+            } else {
+                LauncherActivityInfoCompat launcherActInfo =
+                        mLauncherApps.resolveActivity(intent, user);
+                CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
+
+                shortcutInfo.setIcon(entry.icon);
+                shortcutInfo.title = entry.title;
+                shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
+            }
+        }
+    }
+
+
+    public Bitmap getDefaultIcon(UserHandleCompat user) {
+        if (!mDefaultIcons.containsKey(user)) {
+            mDefaultIcons.put(user, makeDefaultIcon(user));
+        }
+        return mDefaultIcons.get(user);
+    }
+
+    public Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
             HashMap<Object, CharSequence> labelCache) {
         synchronized (mCache) {
-            if (resolveInfo == null || component == null) {
+            if (info == null || component == null) {
                 return null;
             }
 
-            CacheEntry entry = cacheLocked(component, resolveInfo, labelCache);
+            CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
             return entry.icon;
         }
     }
 
-    public boolean isDefaultIcon(Bitmap icon) {
-        return mDefaultIcon == icon;
+    public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
+        return mDefaultIcons.get(user) == icon;
     }
 
-    private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info,
-            HashMap<Object, CharSequence> labelCache) {
-        CacheEntry entry = mCache.get(componentName);
+    private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
+            HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
+        CacheKey cacheKey = new CacheKey(componentName, user);
+        CacheEntry entry = mCache.get(cacheKey);
         if (entry == null) {
             entry = new CacheEntry();
 
-            mCache.put(componentName, entry);
+            mCache.put(cacheKey, entry);
 
-            ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
-            if (labelCache != null && labelCache.containsKey(key)) {
-                entry.title = labelCache.get(key).toString();
+            if (info != null) {
+                ComponentName labelKey = info.getComponentName();
+                if (labelCache != null && labelCache.containsKey(labelKey)) {
+                    entry.title = labelCache.get(labelKey).toString();
+                } else {
+                    entry.title = info.getLabel().toString();
+                    if (labelCache != null) {
+                        labelCache.put(labelKey, entry.title);
+                    }
+                }
+
+                entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+                entry.icon = Utilities.createIconBitmap(
+                        info.getBadgedIcon(mIconDpi), mContext);
             } else {
-                entry.title = info.loadLabel(mPackageManager).toString();
-                if (labelCache != null) {
-                    labelCache.put(key, entry.title);
+                entry.title = "";
+                Bitmap preloaded = getPreloadedIcon(componentName, user);
+                if (preloaded != null) {
+                    if (DEBUG) Log.d(TAG, "using preloaded icon for " +
+                            componentName.toShortString());
+                    entry.icon = preloaded;
+                } else {
+                    if (usePackageIcon) {
+                        CacheEntry packageEntry = getEntryForPackage(
+                                componentName.getPackageName(), user);
+                        if (packageEntry != null) {
+                            if (DEBUG) Log.d(TAG, "using package default icon for " +
+                                    componentName.toShortString());
+                            entry.icon = packageEntry.icon;
+                            entry.title = packageEntry.title;
+                        }
+                    }
+                    if (entry.icon == null) {
+                        if (DEBUG) Log.d(TAG, "using default icon for " +
+                                componentName.toShortString());
+                        entry.icon = getDefaultIcon(user);
+                    }
                 }
             }
-            if (entry.title == null) {
-                entry.title = info.activityInfo.name;
+        }
+        return entry;
+    }
+
+    /**
+     * Adds a default package entry in the cache. This entry is not persisted and will be removed
+     * when the cache is flushed.
+     */
+    public void cachePackageInstallInfo(String packageName, UserHandleCompat user,
+            Bitmap icon, CharSequence title) {
+        remove(packageName, user);
+
+        CacheEntry entry = getEntryForPackage(packageName, user);
+        if (!TextUtils.isEmpty(title)) {
+            entry.title = title;
+        }
+        if (icon != null) {
+            entry.icon = Utilities.createIconBitmap(
+                    new BitmapDrawable(mContext.getResources(), icon), mContext);
+        }
+    }
+
+    /**
+     * Gets an entry for the package, which can be used as a fallback entry for various components.
+     */
+    private CacheEntry getEntryForPackage(String packageName, UserHandleCompat user) {
+        ComponentName cn = getPackageComponent(packageName);
+        CacheKey cacheKey = new CacheKey(cn, user);
+        CacheEntry entry = mCache.get(cacheKey);
+        if (entry == null) {
+            entry = new CacheEntry();
+            entry.title = "";
+            mCache.put(cacheKey, entry);
+
+            try {
+                ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, 0);
+                entry.title = info.loadLabel(mPackageManager);
+                entry.icon = Utilities.createIconBitmap(info.loadIcon(mPackageManager), mContext);
+            } catch (NameNotFoundException e) {
+                if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
             }
 
-            entry.icon = Utilities.createIconBitmap(
-                    getFullResIcon(info), mContext);
+            if (entry.icon == null) {
+                entry.icon = getPreloadedIcon(cn, user);
+            }
         }
         return entry;
     }
@@ -236,11 +425,143 @@
     public HashMap<ComponentName,Bitmap> getAllIcons() {
         synchronized (mCache) {
             HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
-            for (ComponentName cn : mCache.keySet()) {
-                final CacheEntry e = mCache.get(cn);
-                set.put(cn, e.icon);
+            for (CacheKey ck : mCache.keySet()) {
+                final CacheEntry e = mCache.get(ck);
+                set.put(ck.componentName, e.icon);
             }
             return set;
         }
     }
+
+    /**
+     * Pre-load an icon into the persistent cache.
+     *
+     * <P>Queries for a component that does not exist in the package manager
+     * will be answered by the persistent cache.
+     *
+     * @param context application context
+     * @param componentName the icon should be returned for this component
+     * @param icon the icon to be persisted
+     * @param dpi the native density of the icon
+     */
+    public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon,
+            int dpi) {
+        // TODO rescale to the correct native DPI
+        try {
+            PackageManager packageManager = context.getPackageManager();
+            packageManager.getActivityIcon(componentName);
+            // component is present on the system already, do nothing
+            return;
+        } catch (PackageManager.NameNotFoundException e) {
+            // pass
+        }
+
+        final String key = componentName.flattenToString();
+        FileOutputStream resourceFile = null;
+        try {
+            resourceFile = context.openFileOutput(getResourceFilename(componentName),
+                    Context.MODE_PRIVATE);
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) {
+                byte[] buffer = os.toByteArray();
+                resourceFile.write(buffer, 0, buffer.length);
+            } else {
+                Log.w(TAG, "failed to encode cache for " + key);
+                return;
+            }
+        } catch (FileNotFoundException e) {
+            Log.w(TAG, "failed to pre-load cache for " + key, e);
+        } catch (IOException e) {
+            Log.w(TAG, "failed to pre-load cache for " + key, e);
+        } finally {
+            if (resourceFile != null) {
+                try {
+                    resourceFile.close();
+                } catch (IOException e) {
+                    Log.d(TAG, "failed to save restored icon for: " + key, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Read a pre-loaded icon from the persistent icon cache.
+     *
+     * @param componentName the component that should own the icon
+     * @returns a bitmap if one is cached, or null.
+     */
+    private Bitmap getPreloadedIcon(ComponentName componentName, UserHandleCompat user) {
+        final String key = componentName.flattenToShortString();
+
+        // We don't keep icons for other profiles in persistent cache.
+        if (!user.equals(UserHandleCompat.myUserHandle())) {
+            return null;
+        }
+
+        if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key);
+        Bitmap icon = null;
+        FileInputStream resourceFile = null;
+        try {
+            resourceFile = mContext.openFileInput(getResourceFilename(componentName));
+            byte[] buffer = new byte[1024];
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            int bytesRead = 0;
+            while(bytesRead >= 0) {
+                bytes.write(buffer, 0, bytesRead);
+                bytesRead = resourceFile.read(buffer, 0, buffer.length);
+            }
+            if (DEBUG) Log.d(TAG, "read " + bytes.size());
+            icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size());
+            if (icon == null) {
+                Log.w(TAG, "failed to decode pre-load icon for " + key);
+            }
+        } catch (FileNotFoundException e) {
+            if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key);
+        } catch (IOException e) {
+            Log.w(TAG, "failed to read pre-load icon for: " + key, e);
+        } finally {
+            if(resourceFile != null) {
+                try {
+                    resourceFile.close();
+                } catch (IOException e) {
+                    Log.d(TAG, "failed to manage pre-load icon file: " + key, e);
+                }
+            }
+        }
+
+        return icon;
+    }
+
+    /**
+     * Remove a pre-loaded icon from the persistent icon cache.
+     *
+     * @param componentName the component that should own the icon
+     * @returns true on success
+     */
+    public boolean deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
+        // We don't keep icons for other profiles in persistent cache.
+        if (!user.equals(UserHandleCompat.myUserHandle())) {
+            return false;
+        }
+        if (componentName == null) {
+            return false;
+        }
+        if (mCache.remove(componentName) != null) {
+            if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
+        }
+        boolean success = mContext.deleteFile(getResourceFilename(componentName));
+        if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
+
+        return success;
+    }
+
+    private static String getResourceFilename(ComponentName component) {
+        String resourceName = component.flattenToShortString();
+        String filename = resourceName.replace(File.separatorChar, '_');
+        return RESOURCE_FILE_PREFIX + filename;
+    }
+
+    static ComponentName getPackageComponent(String packageName) {
+        return new ComponentName(packageName, EMPTY_CLASS_NAME);
+    }
 }
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 374238c..7e55af2 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -26,6 +26,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.launcher3.compat.UserHandleCompat;
+
 public class InfoDropTarget extends ButtonDropTarget {
 
     private ColorStateList mOriginalTextColor;
@@ -49,6 +51,13 @@
         Resources r = getResources();
         mHoverColor = r.getColor(R.color.info_target_hover_tint);
         mDrawable = (TransitionDrawable) getCurrentDrawable();
+
+        if (mDrawable == null) {
+            // TODO: investigate why this is ever happening. Presently only on one known device.
+            mDrawable = (TransitionDrawable) r.getDrawable(R.drawable.info_target_selector);
+            setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null);
+        }
+
         if (null != mDrawable) {
             mDrawable.setCrossFadeEnabled(true);
         }
@@ -75,8 +84,15 @@
         } else if (d.dragInfo instanceof PendingAddItemInfo) {
             componentName = ((PendingAddItemInfo) d.dragInfo).componentName;
         }
+        final UserHandleCompat user;
+        if (d.dragInfo instanceof ItemInfo) {
+            user = ((ItemInfo) d.dragInfo).user;
+        } else {
+            user = UserHandleCompat.myUserHandle();
+        }
+
         if (componentName != null) {
-            mLauncher.startApplicationDetailsActivity(componentName);
+            mLauncher.startApplicationDetailsActivity(componentName, user);
         }
 
         // There is no post-drop animation, so clean up the DragView now
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 7ab4e04..2edde4f 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -17,6 +17,7 @@
 package com.android.launcher3;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -29,6 +30,8 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.launcher3.compat.UserHandleCompat;
+
 import org.json.JSONObject;
 import org.json.JSONStringer;
 import org.json.JSONTokener;
@@ -280,19 +283,27 @@
                 final boolean exists = LauncherModel.shortcutExists(context, name, intent);
                 //final boolean allowDuplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
 
-                // TODO-XXX: Disable duplicates for now
-                if (!exists /* && allowDuplicate */) {
+                // If the intent specifies a package, make sure the package exists
+                String packageName = intent.getPackage();
+                if (packageName == null) {
+                    packageName = intent.getComponent() == null ? null :
+                        intent.getComponent().getPackageName();
+                }
+                if (packageName != null && !packageName.isEmpty()) {
+                    UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
+                    if (!LauncherModel.isValidPackage(context, packageName, myUserHandle)) {
+                        if (DBG) Log.d(TAG, "Ignoring shortcut for absent package:" + intent);
+                        continue;
+                    }
+                }
+
+                if (!exists) {
                     // Generate a shortcut info to add into the model
                     ShortcutInfo info = getShortcutInfo(context, pendingInfo.data,
                             pendingInfo.launchIntent);
                     addShortcuts.add(info);
                 }
-                /*
-                else if (exists && !allowDuplicate) {
-                    result = INSTALL_SHORTCUT_IS_DUPLICATE;
-                    duplicateName = name;
-                }
-                */
+
             }
 
             // Notify the user once if we weren't able to place any duplicates
@@ -304,7 +315,7 @@
             // Add the new apps to the model and bind them
             if (!addShortcuts.isEmpty()) {
                 LauncherAppState app = LauncherAppState.getInstance();
-                app.getModel().addAndBindAddedApps(context, addShortcuts, new ArrayList<AppInfo>());
+                app.getModel().addAndBindAddedWorkspaceApps(context, addShortcuts);
             }
         }
     }
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index 36ba6c1..09b77f7 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -17,24 +17,34 @@
 package com.android.launcher3;
 
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.util.Log;
 
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * Represents an item in the launcher.
  */
 public class ItemInfo {
+
+    /**
+     * Intent extra to store the profile. Format: UserHandle
+     */
+    static final String EXTRA_PROFILE = "profile";
     
     static final int NO_ID = -1;
     
     /**
      * The id in the settings database for this item
      */
-    long id = NO_ID;
+    public long id = NO_ID;
     
     /**
      * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
@@ -42,7 +52,7 @@
      * {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or
      * {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
      */
-    int itemType;
+    public int itemType;
     
     /**
      * The id of the container that holds this item. For the desktop, this will be 
@@ -50,27 +60,27 @@
      * will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders
      * it will be the id of the folder.
      */
-    long container = NO_ID;
+    public long container = NO_ID;
     
     /**
      * Iindicates the screen in which the shortcut appears.
      */
-    long screenId = -1;
+    public long screenId = -1;
     
     /**
      * Indicates the X position of the associated cell.
      */
-    int cellX = -1;
+    public int cellX = -1;
 
     /**
      * Indicates the Y position of the associated cell.
      */
-    int cellY = -1;
+    public int cellY = -1;
 
     /**
      * Indicates the X cell span.
      */
-    int spanX = 1;
+    public int spanX = 1;
 
     /**
      * Indicates the Y cell span.
@@ -80,17 +90,17 @@
     /**
      * Indicates the minimum X cell span.
      */
-    int minSpanX = 1;
+    public int minSpanX = 1;
 
     /**
      * Indicates the minimum Y cell span.
      */
-    int minSpanY = 1;
+    public int minSpanY = 1;
 
     /**
      * Indicates that this item needs to be updated in the db
      */
-    boolean requiresDbUpdate = false;
+    public boolean requiresDbUpdate = false;
 
     /**
      * Title of the item
@@ -98,14 +108,28 @@
     CharSequence title;
 
     /**
+     * Content description of the item.
+     */
+    CharSequence contentDescription;
+
+    /**
      * The position of the item in a drag-and-drop operation.
      */
     int[] dropPos = null;
 
+    UserHandleCompat user;
+
     ItemInfo() {
+        user = UserHandleCompat.myUserHandle();
     }
 
     ItemInfo(ItemInfo info) {
+        copyFrom(info);
+        // tempdebug:
+        LauncherModel.checkItemInfo(this);
+    }
+
+    public void copyFrom(ItemInfo info) {
         id = info.id;
         cellX = info.cellX;
         cellY = info.cellY;
@@ -114,20 +138,22 @@
         screenId = info.screenId;
         itemType = info.itemType;
         container = info.container;
-        // tempdebug:
-        LauncherModel.checkItemInfo(this);
+        user = info.user;
+        contentDescription = info.contentDescription;
     }
 
-    protected Intent getIntent() {
+    public Intent getIntent() {
         throw new RuntimeException("Unexpected Intent");
     }
 
     /**
      * Write the fields of this item to the DB
      * 
+     * @param context A context object to use for getting UserManagerCompat
      * @param values
      */
-    void onAddToDatabase(ContentValues values) { 
+
+    void onAddToDatabase(Context context, ContentValues values) {
         values.put(LauncherSettings.BaseLauncherColumns.ITEM_TYPE, itemType);
         values.put(LauncherSettings.Favorites.CONTAINER, container);
         values.put(LauncherSettings.Favorites.SCREEN, screenId);
@@ -135,6 +161,13 @@
         values.put(LauncherSettings.Favorites.CELLY, cellY);
         values.put(LauncherSettings.Favorites.SPANX, spanX);
         values.put(LauncherSettings.Favorites.SPANY, spanY);
+        long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
+        values.put(LauncherSettings.Favorites.PROFILE_ID, serialNumber);
+
+        if (screenId == Workspace.EXTRA_EMPTY_SCREEN_ID) {
+            // We should never persist an item on the extra empty screen.
+            throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
+        }
     }
 
     void updateValuesWithCoordinates(ContentValues values, int cellX, int cellY) {
@@ -178,6 +211,7 @@
     public String toString() {
         return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
             + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
-            + " spanY=" + spanY + " dropPos=" + dropPos + ")";
+            + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
+            + " user=" + user + ")";
     }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 09c15a7..42ec4fb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -22,11 +22,13 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.AlertDialog;
 import android.app.SearchManager;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
@@ -37,6 +39,7 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
@@ -44,25 +47,25 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
 import android.os.StrictMode;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.speech.RecognizerIntent;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
@@ -70,6 +73,7 @@
 import android.text.method.TextKeyListener;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
@@ -81,13 +85,16 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnLongClickListener;
+import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Advanceable;
 import android.widget.FrameLayout;
@@ -96,6 +103,14 @@
 import android.widget.Toast;
 
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.PagedView.PageSwitchListener;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -105,6 +120,9 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -113,13 +131,12 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
 /**
  * Default launcher application.
  */
 public class Launcher extends Activity
         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
-                   View.OnTouchListener {
+                   View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener {
     static final String TAG = "Launcher";
     static final boolean LOGD = false;
 
@@ -133,12 +150,12 @@
 
     private static final int REQUEST_CREATE_SHORTCUT = 1;
     private static final int REQUEST_CREATE_APPWIDGET = 5;
-    private static final int REQUEST_PICK_APPLICATION = 6;
     private static final int REQUEST_PICK_SHORTCUT = 7;
     private static final int REQUEST_PICK_APPWIDGET = 9;
     private static final int REQUEST_PICK_WALLPAPER = 10;
 
     private static final int REQUEST_BIND_APPWIDGET = 11;
+    private static final int REQUEST_RECONFIGURE_APPWIDGET = 12;
 
     /**
      * IntentStarter uses request codes starting with this. This must be greater than all activity
@@ -189,9 +206,13 @@
     // Type: int[]
     private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids";
 
-
+    static final String INTRO_SCREEN_DISMISSED = "launcher.intro_screen_dismissed";
     static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed";
 
+    static final String FIRST_LOAD_COMPLETE = "launcher.first_load_complete";
+    static final String ACTION_FIRST_LOAD_COMPLETE =
+            "com.android.launcher3.action.FIRST_LOAD_COMPLETE";
+
     private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
     private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME =
             "com.android.launcher.toolbar_search_icon";
@@ -208,9 +229,12 @@
     private State mState = State.WORKSPACE;
     private AnimatorSet mStateAnimation;
 
+    private boolean mIsSafeModeEnabled;
+
     static final int APPWIDGET_HOST_ID = 1024;
     public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
     private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
+    private static final int ACTIVITY_START_DELAY = 1000;
 
     private static final Object sLock = new Object();
     private static int sScreen = DEFAULT_SCREEN;
@@ -222,6 +246,7 @@
     private static int NEW_APPS_PAGE_MOVE_DELAY = 500;
     private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
     private static int NEW_APPS_ANIMATION_DELAY = 500;
+    private static final int SINGLE_FRAME_DELAY = 16;
 
     private final BroadcastReceiver mCloseSystemDialogsReceiver
             = new CloseSystemDialogsIntentReceiver();
@@ -235,9 +260,8 @@
     private DragLayer mDragLayer;
     private DragController mDragController;
     private View mWeightWatcher;
-    private LauncherClings mLauncherClings;
 
-    private AppWidgetManager mAppWidgetManager;
+    private AppWidgetManagerCompat mAppWidgetManager;
     private LauncherAppWidgetHost mAppWidgetHost;
 
     private ItemInfo mPendingAddInfo = new ItemInfo();
@@ -249,7 +273,7 @@
     private FolderInfo mFolderInfo;
 
     private Hotseat mHotseat;
-    private View mOverviewPanel;
+    private ViewGroup mOverviewPanel;
 
     private View mAllAppsButton;
 
@@ -257,7 +281,7 @@
     private AppsCustomizeTabHost mAppsCustomizeTabHost;
     private AppsCustomizePagedView mAppsCustomizeContent;
     private boolean mAutoAdvanceRunning = false;
-    private View mQsbBar;
+    private View mQsb;
 
     private Bundle mSavedState;
     // We set the state in both onCreate and then onNewIntent in some cases, which causes both
@@ -277,9 +301,6 @@
     private ArrayList<Runnable> mBindOnResumeCallbacks = new ArrayList<Runnable>();
     private ArrayList<Runnable> mOnResumeCallbacks = new ArrayList<Runnable>();
 
-    // Keep track of whether the user has left launcher
-    private static boolean sPausedFromUserAction = false;
-
     private Bundle mSavedInstanceState;
 
     private LauncherModel mModel;
@@ -311,10 +332,6 @@
     // External icons saved in case of resource changes, orientation, etc.
     private static Drawable.ConstantState[] sGlobalSearchIcon = new Drawable.ConstantState[2];
     private static Drawable.ConstantState[] sVoiceSearchIcon = new Drawable.ConstantState[2];
-    private static Drawable.ConstantState[] sAppMarketIcon = new Drawable.ConstantState[2];
-
-    private Intent mAppMarketIntent = null;
-    private static final boolean DISABLE_MARKET_BUTTON = true;
 
     private Drawable mWorkspaceBackgroundDrawable;
 
@@ -351,8 +368,7 @@
         }
     };
 
-    private static ArrayList<PendingAddArguments> sPendingAddList
-            = new ArrayList<PendingAddArguments>();
+    private static PendingAddArguments sPendingAddItem;
 
     public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
 
@@ -363,10 +379,13 @@
         long screenId;
         int cellX;
         int cellY;
+        int appWidgetId;
     }
 
     private Stats mStats;
 
+    FocusIndicatorView mFocusHandler;
+
     static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);
     }
@@ -392,7 +411,7 @@
 
         LauncherAppState.setApplicationContext(getApplicationContext());
         LauncherAppState app = LauncherAppState.getInstance();
-
+        LauncherAppState.getLauncherProvider().setLauncherProviderChangeListener(this);
         // Determine the dynamic grid properties
         Point smallestSize = new Point();
         Point largestSize = new Point();
@@ -413,16 +432,16 @@
         // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
         mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
                 Context.MODE_PRIVATE);
+        mIsSafeModeEnabled = getPackageManager().isSafeMode();
         mModel = app.setLauncher(this);
         mIconCache = app.getIconCache();
         mIconCache.flushInvalidIcons(grid);
         mDragController = new DragController(this);
-        mLauncherClings = new LauncherClings(this);
         mInflater = getLayoutInflater();
 
         mStats = new Stats(this);
 
-        mAppWidgetManager = AppWidgetManager.getInstance(this);
+        mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
 
         mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
         mAppWidgetHost.startListening();
@@ -437,7 +456,6 @@
                     Environment.getExternalStorageDirectory() + "/launcher");
         }
 
-
         checkForLocaleChange();
         setContentView(R.layout.launcher);
 
@@ -456,7 +474,7 @@
         }
 
         if (!mRestoring) {
-            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE || sPausedFromUserAction) {
+            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
                 // If the user leaves launcher, then we should just load items asynchronously when
                 // they return.
                 mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
@@ -479,25 +497,16 @@
         // On large interfaces, we want the screen to auto-rotate based on the current orientation
         unlockScreenOrientation(true);
 
-        // The two first run cling paths are mutually exclusive, if the launcher is preinstalled
-        // on the device, then we always show the first run cling experience (or if there is no
-        // launcher2). Otherwise, we prompt the user upon started for migration
-        showFirstRunActivity();
-        if (mLauncherClings.shouldShowFirstRunOrMigrationClings()) {
-            if (mModel.canMigrateFromOldLauncherDb(this)) {
-                mLauncherClings.showMigrationCling();
-            } else {
-                mLauncherClings.showFirstRunCling();
-            }
+        if (shouldShowIntroScreen()) {
+            showIntroScreen();
         } else {
-            mLauncherClings.removeFirstRunAndMigrationClings();
+            showFirstRunActivity();
+            showFirstRunClings();
         }
     }
 
-    protected void onUserLeaveHint() {
-        super.onUserLeaveHint();
-        sPausedFromUserAction = true;
-    }
+    @Override
+    public void onLauncherProviderChange() { }
 
     /** To be overriden by subclasses to hint to Launcher that we have custom content */
     protected boolean hasCustomContentToLeft() {
@@ -505,26 +514,11 @@
     }
 
     /**
-     * To be overridden by subclasses to create the custom content and call
+     * To be overridden by subclasses to populate the custom content container and call
      * {@link #addToCustomContentPage}. This will only be invoked if
      * {@link #hasCustomContentToLeft()} is {@code true}.
      */
-    protected void addCustomContentToLeft() {
-    }
-
-    /**
-     * To be overridden by subclasses to indicate that there is an activity to launch
-     * before showing the standard launcher experience.
-     */
-    protected boolean hasFirstRunActivity() {
-        return false;
-    }
-
-    /**
-     * To be overridden by subclasses to launch any first run activity
-     */
-    protected Intent getFirstRunActivity() {
-        return null;
+    protected void populateCustomContentContainer() {
     }
 
     /**
@@ -539,8 +533,8 @@
 
         if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
             // Create the custom content page and call the subclass to populate it.
-            mWorkspace.createCustomContentPage();
-            addCustomContentToLeft();
+            mWorkspace.createCustomContentContainer();
+            populateCustomContentContainer();
         } else if (mWorkspace.hasCustomContent() && !hasCustomContentToLeft()) {
             mWorkspace.removeCustomContentPage();
         }
@@ -551,11 +545,7 @@
         boolean voiceVisible = false;
         // If we have a saved version of these external icons, we load them up immediately
         int coi = getCurrentOrientationIndexForGlobalIcons();
-        if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null ||
-                sAppMarketIcon[coi] == null) {
-            if (!DISABLE_MARKET_BUTTON) {
-                updateAppMarketIcon();
-            }
+        if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null) {
             searchVisible = updateGlobalSearchIcon();
             voiceVisible = updateVoiceSearchIcon(searchVisible);
         }
@@ -567,9 +557,6 @@
             updateVoiceSearchIcon(sVoiceSearchIcon[coi]);
             voiceVisible = true;
         }
-        if (!DISABLE_MARKET_BUTTON && sAppMarketIcon[coi] != null) {
-            updateAppMarketIcon(sAppMarketIcon[coi]);
-        }
         if (mSearchDropTargetBar != null) {
             mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, voiceVisible);
         }
@@ -702,19 +689,20 @@
         }
     }
 
-    /**
-     * Copied from View -- the View version of the method isn't called
-     * anywhere else in our process and only exists for API level 17+,
-     * so it's ok to keep our own version with no API requirement.
-     */
     public static int generateViewId() {
-        for (;;) {
-            final int result = sNextGeneratedId.get();
-            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
-            int newValue = result + 1;
-            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
-            if (sNextGeneratedId.compareAndSet(result, newValue)) {
-                return result;
+        if (Build.VERSION.SDK_INT >= 17) {
+            return View.generateViewId();
+        } else {
+            // View.generateViewId() is not available. The following fallback logic is a copy
+            // of its implementation.
+            for (;;) {
+                final int result = sNextGeneratedId.get();
+                // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+                int newValue = result + 1;
+                if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
+                if (sNextGeneratedId.compareAndSet(result, newValue)) {
+                    return result;
+                }
             }
         }
     }
@@ -734,40 +722,39 @@
      * Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
      * a configuration step, this allows the proper animations to run after other transitions.
      */
-    private boolean completeAdd(PendingAddArguments args) {
-        boolean result = false;
+    private long completeAdd(PendingAddArguments args) {
+        long screenId = args.screenId;
+        if (args.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+            // When the screen id represents an actual screen (as opposed to a rank) we make sure
+            // that the drop page actually exists.
+            screenId = ensurePendingDropLayoutExists(args.screenId);
+        }
+
         switch (args.requestCode) {
-            case REQUEST_PICK_APPLICATION:
-                completeAddApplication(args.intent, args.container, args.screenId, args.cellX,
-                        args.cellY);
-                break;
-            case REQUEST_PICK_SHORTCUT:
-                processShortcut(args.intent);
-                break;
             case REQUEST_CREATE_SHORTCUT:
-                completeAddShortcut(args.intent, args.container, args.screenId, args.cellX,
+                completeAddShortcut(args.intent, args.container, screenId, args.cellX,
                         args.cellY);
-                result = true;
                 break;
             case REQUEST_CREATE_APPWIDGET:
-                int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-                completeAddAppWidget(appWidgetId, args.container, args.screenId, null, null);
-                result = true;
+                completeAddAppWidget(args.appWidgetId, args.container, screenId, null, null);
+                break;
+            case REQUEST_RECONFIGURE_APPWIDGET:
+                completeRestoreAppWidget(args.appWidgetId);
                 break;
         }
         // Before adding this resetAddInfo(), after a shortcut was added to a workspace screen,
         // if you turned the screen off and then back while in All Apps, Launcher would not
         // return to the workspace. Clearing mAddInfo.container here fixes this issue
         resetAddInfo();
-        return result;
+        return screenId;
     }
 
     @Override
     protected void onActivityResult(
             final int requestCode, final int resultCode, final Intent data) {
         // Reset the startActivity waiting flag
-        mWaitingForResult = false;
-        int pendingAddWidgetId = mPendingAddWidgetId;
+        setWaitingForResult(false);
+        final int pendingAddWidgetId = mPendingAddWidgetId;
         mPendingAddWidgetId = -1;
 
         Runnable exitSpringLoaded = new Runnable() {
@@ -783,7 +770,7 @@
                     data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
             if (resultCode == RESULT_CANCELED) {
                 completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
-                mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+                mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
                         ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             } else if (resultCode == RESULT_OK) {
                 addAppWidgetImpl(appWidgetId, mPendingAddInfo, null,
@@ -800,6 +787,7 @@
         boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
                 requestCode == REQUEST_CREATE_APPWIDGET);
 
+        final boolean workspaceLocked = isWorkspaceLocked();
         // We have special handling for widgets
         if (isWidgetDrop) {
             final int appWidgetId;
@@ -812,33 +800,66 @@
             }
 
             final int result;
-            final Runnable onComplete;
             if (appWidgetId < 0 || resultCode == RESULT_CANCELED) {
-                Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\" +
-                        "widget configuration activity.");
+                Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not " +
+                        "returned from the widget configuration activity.");
                 result = RESULT_CANCELED;
                 completeTwoStageWidgetDrop(result, appWidgetId);
-                onComplete = new Runnable() {
+                final Runnable onComplete = new Runnable() {
                     @Override
                     public void run() {
                         exitSpringLoadedDragModeDelayed(false, 0, null);
                     }
                 };
+                if (workspaceLocked) {
+                    // No need to remove the empty screen if we're mid-binding, as the
+                    // the bind will not add the empty screen.
+                    mWorkspace.postDelayed(onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY);
+                } else {
+                    mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
+                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
+                }
             } else {
-                result = resultCode;
-                final CellLayout dropLayout =
-                        (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
-                dropLayout.setDropPending(true);
-                onComplete = new Runnable() {
-                    @Override
-                    public void run() {
-                        completeTwoStageWidgetDrop(result, appWidgetId);
-                        dropLayout.setDropPending(false);
+                if (!workspaceLocked) {
+                    if (mPendingAddInfo.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                        // When the screen id represents an actual screen (as opposed to a rank)
+                        // we make sure that the drop page actually exists.
+                        mPendingAddInfo.screenId =
+                                ensurePendingDropLayoutExists(mPendingAddInfo.screenId);
                     }
-                };
+                    final CellLayout dropLayout = mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
+
+                    dropLayout.setDropPending(true);
+                    final Runnable onComplete = new Runnable() {
+                        @Override
+                        public void run() {
+                            completeTwoStageWidgetDrop(resultCode, appWidgetId);
+                            dropLayout.setDropPending(false);
+                        }
+                    };
+                    mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete,
+                            ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
+                } else {
+                    PendingAddArguments args = preparePendingAddArgs(requestCode, data, appWidgetId,
+                            mPendingAddInfo);
+                    sPendingAddItem = args;
+                }
             }
-            mWorkspace.removeExtraEmptyScreen(true, onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY,
-                    false);
+            return;
+        }
+
+        if (requestCode == REQUEST_RECONFIGURE_APPWIDGET) {
+            if (resultCode == RESULT_OK) {
+                // Update the widget view.
+                PendingAddArguments args = preparePendingAddArgs(requestCode, data,
+                        pendingAddWidgetId, mPendingAddInfo);
+                if (workspaceLocked) {
+                    sPendingAddItem = args;
+                } else {
+                    completeAdd(args);
+                }
+            }
+            // Leave the widget in the pending state if the user canceled the configure.
             return;
         }
 
@@ -848,27 +869,54 @@
         // For example, the user would PICK_SHORTCUT for "Music playlist", and we
         // launch over to the Music app to actually CREATE_SHORTCUT.
         if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID) {
-            final PendingAddArguments args = new PendingAddArguments();
-            args.requestCode = requestCode;
-            args.intent = data;
-            args.container = mPendingAddInfo.container;
-            args.screenId = mPendingAddInfo.screenId;
-            args.cellX = mPendingAddInfo.cellX;
-            args.cellY = mPendingAddInfo.cellY;
+            final PendingAddArguments args = preparePendingAddArgs(requestCode, data, -1,
+                    mPendingAddInfo);
             if (isWorkspaceLocked()) {
-                sPendingAddList.add(args);
+                sPendingAddItem = args;
             } else {
                 completeAdd(args);
+                mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
+                        ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
             }
-            mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
-                    ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
         } else if (resultCode == RESULT_CANCELED) {
-            mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+            mWorkspace.removeExtraEmptyScreenDelayed(true, exitSpringLoaded,
                     ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
         }
         mDragLayer.clearAnimatedView();
     }
 
+    private PendingAddArguments preparePendingAddArgs(int requestCode, Intent data, int
+            appWidgetId, ItemInfo info) {
+        PendingAddArguments args = new PendingAddArguments();
+        args.requestCode = requestCode;
+        args.intent = data;
+        args.container = info.container;
+        args.screenId = info.screenId;
+        args.cellX = info.cellX;
+        args.cellY = info.cellY;
+        args.appWidgetId = appWidgetId;
+        return args;
+    }
+
+    /**
+     * Check to see if a given screen id exists. If not, create it at the end, return the new id.
+     *
+     * @param screenId the screen id to check
+     * @return the new screen, or screenId if it exists
+     */
+    private long ensurePendingDropLayoutExists(long screenId) {
+        CellLayout dropLayout =
+                (CellLayout) mWorkspace.getScreenWithId(screenId);
+        if (dropLayout == null) {
+            // it's possible that the add screen was removed because it was
+            // empty and a re-bind occurred
+            mWorkspace.addExtraEmptyScreen();
+            return mWorkspace.commitExtraEmptyScreen();
+        } else {
+            return screenId;
+        }
+    }
+
     private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
         CellLayout cellLayout =
                 (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
@@ -937,9 +985,8 @@
         setWorkspaceBackground(mState == State.WORKSPACE);
 
         mPaused = false;
-        sPausedFromUserAction = false;
         if (mRestoring || mOnResumeNeedsLoad) {
-            mWorkspaceLoading = true;
+            setWorkspaceLoading(true);
             mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
             mRestoring = false;
             mOnResumeNeedsLoad = false;
@@ -980,10 +1027,6 @@
             // Resets the previous workspace icon press state
             mWaitingForResume.setStayPressed(false);
         }
-        if (mAppsCustomizeContent != null) {
-            // 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
@@ -1009,17 +1052,20 @@
             // It is also poassible that onShow will instead be called slightly after first layout
             // if PagedView#setRestorePage was set to the custom content page in onCreate().
             if (mWorkspace.isOnOrMovingToCustomContent()) {
-                mWorkspace.getCustomContentCallbacks().onShow();
+                mWorkspace.getCustomContentCallbacks().onShow(true);
             }
         }
         mWorkspace.updateInteractionForState();
         mWorkspace.onResume();
+
+        PackageInstallerCompat.getInstance(this).onResume();
     }
 
     @Override
     protected void onPause() {
         // Ensure that items added to Launcher are queued until Launcher returns
         InstallShortcutReceiver.enableInstallQueue();
+        PackageInstallerCompat.getInstance(this).onPause();
 
         super.onPause();
         mPaused = true;
@@ -1033,12 +1079,6 @@
         }
     }
 
-    protected void onFinishBindingItems() {
-        if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) {
-            addCustomContentToLeft();
-        }
-    }
-
     QSBScroller mQsbScroller = new QSBScroller() {
         int scrollY = 0;
 
@@ -1059,17 +1099,22 @@
     }
 
     public interface CustomContentCallbacks {
-        // Custom content is completely shown
-        public void onShow();
+        // Custom content is completely shown. {@code fromResume} indicates whether this was caused
+        // by a onResume or by scrolling otherwise.
+        public void onShow(boolean fromResume);
 
         // Custom content is completely hidden
         public void onHide();
 
         // Custom content scroll progress changed. From 0 (not showing) to 1 (fully showing).
         public void onScrollProgressChanged(float progress);
+
+        // Indicates whether the user is allowed to scroll away from the custom content.
+        boolean isScrollingAllowed();
     }
 
-    protected void startSettings() {
+    protected boolean hasSettings() {
+        return false;
     }
 
     public interface QSBScroller {
@@ -1090,7 +1135,9 @@
     @Override
     public Object onRetainNonConfigurationInstance() {
         // Flag the loader to stop early before switching
-        mModel.stopLoader();
+        if (mModel.isCurrentCallbacks(this)) {
+            mModel.stopLoader();
+        }
         if (mAppsCustomizeContent != null) {
             mAppsCustomizeContent.surrender();
         }
@@ -1197,7 +1244,7 @@
             mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
             mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
             mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID);
-            mWaitingForResult = true;
+            setWaitingForResult(true);
             mRestoring = true;
         }
 
@@ -1232,8 +1279,10 @@
         final DragController dragController = mDragController;
 
         mLauncherView = findViewById(R.id.launcher);
+        mFocusHandler = (FocusIndicatorView) findViewById(R.id.focus_indicator);
         mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
         mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
+        mWorkspace.setPageSwitchListener(this);
         mPageIndicators = mDragLayer.findViewById(R.id.page_indicator);
 
         mLauncherView.setSystemUiVisibility(
@@ -1250,13 +1299,13 @@
             mHotseat.setOnLongClickListener(this);
         }
 
-        mOverviewPanel = findViewById(R.id.overview_panel);
+        mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
         View widgetButton = findViewById(R.id.widget_button);
         widgetButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View arg0) {
                 if (!mWorkspace.isSwitchingState()) {
-                    showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+                    onClickAddWidgetButton(arg0);
                 }
             }
         });
@@ -1267,22 +1316,30 @@
             @Override
             public void onClick(View arg0) {
                 if (!mWorkspace.isSwitchingState()) {
-                    startWallpaper();
+                    onClickWallpaperPicker(arg0);
                 }
             }
         });
         wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
 
         View settingsButton = findViewById(R.id.settings_button);
-        settingsButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                if (!mWorkspace.isSwitchingState()) {
-                    startSettings();
+        if (hasSettings()) {
+            settingsButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View arg0) {
+                    if (!mWorkspace.isSwitchingState()) {
+                        onClickSettingsButton(arg0);
+                    }
                 }
-            }
-        });
-        settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
+            });
+            settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
+        } else {
+            settingsButton.setVisibility(View.GONE);
+            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) widgetButton.getLayoutParams();
+            lp.gravity = Gravity.END | Gravity.TOP;
+            widgetButton.requestLayout();
+        }
+
         mOverviewPanel.setAlpha(0f);
 
         // Setup the workspace
@@ -1292,7 +1349,8 @@
         dragController.addDragListener(mWorkspace);
 
         // Get the search/delete bar
-        mSearchDropTargetBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
+        mSearchDropTargetBar = (SearchDropTargetBar)
+                mDragLayer.findViewById(R.id.search_drop_target_bar);
 
         // Setup AppsCustomize
         mAppsCustomizeTabHost = (AppsCustomizeTabHost) findViewById(R.id.apps_customize_pane);
@@ -1326,6 +1384,17 @@
     }
 
     /**
+     * Sets the all apps button. This method is called from {@link Hotseat}.
+     */
+    public void setAllAppsButton(View allAppsButton) {
+        mAllAppsButton = allAppsButton;
+    }
+
+    public View getAllAppsButton() {
+        return mAllAppsButton;
+    }
+
+    /**
      * Creates a view representing a shortcut.
      *
      * @param info The data structure describing the shortcut.
@@ -1348,44 +1417,13 @@
      */
     View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
         BubbleTextView favorite = (BubbleTextView) mInflater.inflate(layoutResId, parent, false);
-        favorite.applyFromShortcutInfo(info, mIconCache);
+        favorite.applyFromShortcutInfo(info, mIconCache, true);
         favorite.setOnClickListener(this);
+        favorite.setOnFocusChangeListener(mFocusHandler);
         return favorite;
     }
 
     /**
-     * Add an application shortcut to the workspace.
-     *
-     * @param data The intent describing the application.
-     * @param cellInfo The position on screen where to create the shortcut.
-     */
-    void completeAddApplication(Intent data, long container, long screenId, int cellX, int cellY) {
-        final int[] cellXY = mTmpAddItemCellCoordinates;
-        final CellLayout layout = getCellLayout(container, screenId);
-
-        // First we check if we already know the exact location where we want to add this item.
-        if (cellX >= 0 && cellY >= 0) {
-            cellXY[0] = cellX;
-            cellXY[1] = cellY;
-        } else if (!layout.findCellForSpan(cellXY, 1, 1)) {
-            showOutOfSpaceMessage(isHotseatLayout(layout));
-            return;
-        }
-
-        final ShortcutInfo info = mModel.getShortcutInfo(getPackageManager(), data, this);
-
-        if (info != null) {
-            info.setActivity(this, data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
-                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-            info.container = ItemInfo.NO_ID;
-            mWorkspace.addApplicationShortcut(info, layout, container, screenId, cellXY[0], cellXY[1],
-                    isWorkspaceLocked(), cellX, cellY);
-        } else {
-            Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
-        }
-    }
-
-    /**
      * Add a shortcut to the workspace.
      *
      * @param data The intent describing the shortcut.
@@ -1535,6 +1573,7 @@
         launcherInfo.spanY = spanXY[1];
         launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
         launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
+        launcherInfo.user = mAppWidgetManager.getUser(appWidgetInfo);
 
         LauncherModel.addItemToDatabase(this, launcherInfo,
                 container, screenId, cellXY[0], cellXY[1], false);
@@ -1587,6 +1626,9 @@
                 mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
                         LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
                                 | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
+            } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED.equals(action)
+                    || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+                getModel().forceReload();
             }
         }
     };
@@ -1599,16 +1641,61 @@
         final IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(Intent.ACTION_USER_PRESENT);
+        // For handling managed profiles
+        filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED);
+        filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED);
         if (ENABLE_DEBUG_INTENTS) {
             filter.addAction(DebugIntents.DELETE_DATABASE);
             filter.addAction(DebugIntents.MIGRATE_DATABASE);
         }
         registerReceiver(mReceiver, filter);
         FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
+        setupTransparentSystemBarsForLmp();
         mAttached = true;
         mVisible = true;
     }
 
+    /**
+     * Sets up transparent navigation and status bars in LMP.
+     * This method is a no-op for other platform versions.
+     */
+    @TargetApi(19)
+    private void setupTransparentSystemBarsForLmp() {
+        // TODO(sansid): use the APIs directly when compiling against L sdk.
+        // Currently we use reflection to access the flags and the API to set the transparency
+        // on the System bars.
+        if (Utilities.isLmpOrAbove()) {
+            try {
+                getWindow().getAttributes().systemUiVisibility |=
+                        (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                Field drawsSysBackgroundsField = WindowManager.LayoutParams.class.getField(
+                        "FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS");
+                getWindow().addFlags(drawsSysBackgroundsField.getInt(null));
+
+                Method setStatusBarColorMethod =
+                        Window.class.getDeclaredMethod("setStatusBarColor", int.class);
+                Method setNavigationBarColorMethod =
+                        Window.class.getDeclaredMethod("setNavigationBarColor", int.class);
+                setStatusBarColorMethod.invoke(getWindow(), Color.TRANSPARENT);
+                setNavigationBarColorMethod.invoke(getWindow(), Color.TRANSPARENT);
+            } catch (NoSuchFieldException e) {
+                Log.w(TAG, "NoSuchFieldException while setting up transparent bars");
+            } catch (NoSuchMethodException ex) {
+                Log.w(TAG, "NoSuchMethodException while setting up transparent bars");
+            } catch (IllegalAccessException e) {
+                Log.w(TAG, "IllegalAccessException while setting up transparent bars");
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG, "IllegalArgumentException while setting up transparent bars");
+            } catch (InvocationTargetException e) {
+                Log.w(TAG, "InvocationTargetException while setting up transparent bars");
+            } finally {}
+        }
+    }
+
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
@@ -1659,11 +1746,6 @@
                     }
                 });
             }
-            // When Launcher comes back to foreground, a different Activity might be responsible for
-            // the app market intent, so refresh the icon
-            if (!DISABLE_MARKET_BUTTON) {
-                updateAppMarketIcon();
-            }
             clearTypedText();
         }
     }
@@ -1754,7 +1836,7 @@
         return mHotseat;
     }
 
-    public View getOverviewPanel() {
+    public ViewGroup getOverviewPanel() {
         return mOverviewPanel;
     }
 
@@ -1770,10 +1852,6 @@
         return mModel;
     }
 
-    public LauncherClings getLauncherClings() {
-        return mLauncherClings;
-    }
-
     protected SharedPreferences getSharedPrefs() {
         return mSharedPrefs;
     }
@@ -1782,7 +1860,7 @@
         getWindow().closeAllPanels();
 
         // Whatever we were doing is hereby canceled.
-        mWaitingForResult = false;
+        setWaitingForResult(false);
     }
 
     @Override
@@ -1922,8 +2000,13 @@
 
         // Stop callbacks from LauncherModel
         LauncherAppState app = (LauncherAppState.getInstance());
-        mModel.stopLoader();
-        app.setLauncher(null);
+
+        // It's possible to receive onDestroy after a new Launcher activity has
+        // been created. In this case, don't interfere with the new Launcher.
+        if (mModel.isCurrentCallbacks(this)) {
+            mModel.stopLoader();
+            app.setLauncher(null);
+        }
 
         try {
             mAppWidgetHost.stopListening();
@@ -1951,6 +2034,7 @@
         mWorkspace = null;
         mDragController = null;
 
+        PackageInstallerCompat.getInstance(this).onStop();
         LauncherAnimUtils.onDestroyActivity();
     }
 
@@ -1960,7 +2044,9 @@
 
     @Override
     public void startActivityForResult(Intent intent, int requestCode) {
-        if (requestCode >= 0) mWaitingForResult = true;
+        if (requestCode >= 0) {
+            setWaitingForResult(true);
+        }
         super.startActivityForResult(intent, requestCode);
     }
 
@@ -1987,14 +2073,25 @@
             sourceBounds = mSearchDropTargetBar.getSearchBarBounds();
         }
 
-        startSearch(initialQuery, selectInitialQuery,
+        boolean clearTextImmediately = startSearch(initialQuery, selectInitialQuery,
                 appSearchData, sourceBounds);
+        if (clearTextImmediately) {
+            clearTypedText();
+        }
     }
 
-    public void startSearch(String initialQuery,
+    /**
+     * Start a text search.
+     *
+     * @return {@code true} if the search will start immediately, so any further keypresses
+     * will be handled directly by the search UI. {@code false} if {@link Launcher} should continue
+     * to buffer keypresses.
+     */
+    public boolean startSearch(String initialQuery,
             boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
         startGlobalSearch(initialQuery, selectInitialQuery,
                 appSearchData, sourceBounds);
+        return false;
     }
 
     /**
@@ -2037,10 +2134,25 @@
         }
     }
 
+    public boolean isOnCustomContent() {
+        return mWorkspace.isOnOrMovingToCustomContent();
+    }
+
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        showOverviewMode(true);
+        if (!isOnCustomContent()) {
+            // Close any open folders
+            closeFolder();
+            // Stop resizing any widgets
+            mWorkspace.exitWidgetResizeMode();
+            if (!mWorkspace.isInOverviewMode()) {
+                // Show the overview mode
+                showOverviewMode(true);
+            } else {
+                showWorkspace(true);
+            }
+        }
         return false;
     }
 
@@ -2055,6 +2167,28 @@
         return mWorkspaceLoading || mWaitingForResult;
     }
 
+    public boolean isWorkspaceLoading() {
+        return mWorkspaceLoading;
+    }
+
+    private void setWorkspaceLoading(boolean value) {
+        boolean isLocked = isWorkspaceLocked();
+        mWorkspaceLoading = value;
+        if (isLocked != isWorkspaceLocked()) {
+            onWorkspaceLockedChanged();
+        }
+    }
+
+    private void setWaitingForResult(boolean value) {
+        boolean isLocked = isWorkspaceLocked();
+        mWaitingForResult = value;
+        if (isLocked != isWorkspaceLocked()) {
+            onWorkspaceLockedChanged();
+        }
+    }
+
+    protected void onWorkspaceLockedChanged() { }
+
     private void resetAddInfo() {
         mPendingAddInfo.container = ItemInfo.NO_ID;
         mPendingAddInfo.screenId = -1;
@@ -2077,10 +2211,9 @@
             mPendingAddWidgetId = appWidgetId;
 
             // Launch over to configure widget, if needed
-            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
-            intent.setComponent(appWidgetInfo.configure);
-            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
-            Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET);
+            mAppWidgetManager.startConfigActivity(appWidgetInfo, appWidgetId, this,
+                    mAppWidgetHost, REQUEST_CREATE_APPWIDGET);
+
         } else {
             // Otherwise just add it
             Runnable onComplete = new Runnable() {
@@ -2093,7 +2226,7 @@
             };
             completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
                     appWidgetInfo);
-            mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false);
+            mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
         }
     }
 
@@ -2164,14 +2297,8 @@
             appWidgetId = getAppWidgetHost().allocateAppWidgetId();
             Bundle options = info.bindOptions;
 
-            boolean success = false;
-            if (options != null) {
-                success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
-                        info.componentName, options);
-            } else {
-                success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
-                        info.componentName);
-            }
+            boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
+                    appWidgetId, info.info, options);
             if (success) {
                 addAppWidgetImpl(appWidgetId, info, null, info.info);
             } else {
@@ -2179,6 +2306,8 @@
                 Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
                 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
+                mAppWidgetManager.getUser(mPendingAddWidgetInfo)
+                    .addToIntent(intent, AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
                 // TODO: we need to make sure that this accounts for the options bundle.
                 // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
                 startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
@@ -2187,21 +2316,7 @@
     }
 
     void processShortcut(Intent intent) {
-        // Handle case where user selected "Applications"
-        String applicationName = getResources().getString(R.string.group_applications);
-        String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
-
-        if (applicationName != null && applicationName.equals(shortcutName)) {
-            Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
-            mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-
-            Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
-            pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
-            pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_application));
-            Utilities.startActivityForResultSafely(this, pickIntent, REQUEST_PICK_APPLICATION);
-        } else {
-            Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
-        }
+        Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
     }
 
     void processWallpaper(Intent intent) {
@@ -2233,12 +2348,6 @@
         sFolders.remove(folder.id);
     }
 
-    protected void startWallpaper() {
-        final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
-        pickWallpaper.setComponent(getWallpaperPickerComponent());
-        startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
-    }
-
     protected ComponentName getWallpaperPickerComponent() {
         return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
     }
@@ -2342,59 +2451,63 @@
 
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
-            // Open shortcut
-            final ShortcutInfo shortcut = (ShortcutInfo) tag;
-            final Intent intent = shortcut.intent;
-
-            // Check for special shortcuts
-            if (intent.getComponent() != null) {
-                final String shortcutClass = intent.getComponent().getClassName();
-
-                if (shortcutClass.equals(WidgetAdder.class.getName())) {
-                    showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
-                    return;
-                } else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
-                    MemoryDumpActivity.startDump(this);
-                    return;
-                } else if (shortcutClass.equals(ToggleWeightWatcher.class.getName())) {
-                    toggleShowWeightWatcher();
-                    return;
-                }
-            }
-
-            // Start activities
-            int[] pos = new int[2];
-            v.getLocationOnScreen(pos);
-            intent.setSourceBounds(new Rect(pos[0], pos[1],
-                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
-
-            boolean success = startActivitySafely(v, intent, tag);
-
-            mStats.recordLaunch(intent, shortcut);
-
-            if (success && v instanceof BubbleTextView) {
-                mWaitingForResume = (BubbleTextView) v;
-                mWaitingForResume.setStayPressed(true);
-            }
+            onClickAppShortcut(v);
         } else if (tag instanceof FolderInfo) {
             if (v instanceof FolderIcon) {
-                FolderIcon fi = (FolderIcon) v;
-                handleFolderClick(fi);
+                onClickFolderIcon(v);
             }
         } else if (v == mAllAppsButton) {
-            if (isAllAppsVisible()) {
-                showWorkspace(true);
-            } else {
-                onClickAllAppsButton(v);
+            onClickAllAppsButton(v);
+        } else if (tag instanceof AppInfo) {
+            startAppShortcutOrInfoActivity(v);
+        } else if (tag instanceof LauncherAppWidgetInfo) {
+            if (v instanceof PendingAppWidgetHostView) {
+                onClickPendingWidget((PendingAppWidgetHostView) v);
             }
         }
     }
 
+    public void onClickPagedViewIcon(View v) {
+        startAppShortcutOrInfoActivity(v);
+    }
+
     public boolean onTouch(View v, MotionEvent event) {
         return false;
     }
 
     /**
+     * Event handler for the app widget view which has not fully restored.
+     */
+    public void onClickPendingWidget(final PendingAppWidgetHostView v) {
+        final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
+        if (v.isReadyForClickSetup()) {
+            int widgetId = info.appWidgetId;
+            AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
+            if (appWidgetInfo != null) {
+                mPendingAddWidgetInfo = appWidgetInfo;
+                mPendingAddInfo.copyFrom(info);
+                mPendingAddWidgetId = widgetId;
+
+                AppWidgetManagerCompat.getInstance(this).startConfigActivity(appWidgetInfo,
+                        info.appWidgetId, this, mAppWidgetHost, REQUEST_RECONFIGURE_APPWIDGET);
+            }
+        } else if (info.installProgress < 0) {
+            // The install has not been queued
+            final String packageName = info.providerName.getPackageName();
+            showBrokenAppInstallDialog(packageName,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        startActivitySafely(v, LauncherModel.getMarketIntent(packageName), info);
+                    }
+                });
+        } else {
+            // Download has started.
+            final String packageName = info.providerName.getPackageName();
+            startActivitySafely(v, LauncherModel.getMarketIntent(packageName), info);
+        }
+    }
+
+    /**
      * Event handler for the search button
      *
      * @param v The view that was clicked.
@@ -2440,129 +2553,119 @@
      *
      * @param v The view that was clicked.
      */
-    public void onClickAllAppsButton(View v) {
-        showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
-    }
-
-    public void onTouchDownAllAppsButton(View v) {
-        // Provide the same haptic feedback that the system offers for virtual keys.
-        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
-    }
-
-    public void performHapticFeedbackOnTouchDown(View v) {
-        // Provide the same haptic feedback that the system offers for virtual keys.
-        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
-    }
-
-    public View.OnTouchListener getHapticFeedbackTouchListener() {
-        if (mHapticFeedbackTouchListener == null) {
-            mHapticFeedbackTouchListener = new View.OnTouchListener() {
-                @Override
-                public boolean onTouch(View v, MotionEvent event) {
-                    if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
-                        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
-                    }
-                    return false;
-                }
-            };
-        }
-        return mHapticFeedbackTouchListener;
-    }
-
-    public void onClickAppMarketButton(View v) {
-        if (!DISABLE_MARKET_BUTTON) {
-            if (mAppMarketIntent != null) {
-                startActivitySafely(v, mAppMarketIntent, "app market");
-            } else {
-                Log.e(TAG, "Invalid app market intent.");
-            }
-        }
-    }
-
-    /**
-     * Called when the user stops interacting with the launcher.
-     * This implies that the user is now on the homescreen and is not doing housekeeping.
-     */
-    protected void onInteractionEnd() {}
-
-    /**
-     * Called when the user starts interacting with the launcher.
-     * The possible interactions are:
-     *  - open all apps
-     *  - reorder an app shortcut, or a widget
-     *  - open the overview mode.
-     * This is a good time to stop doing things that only make sense
-     * when the user is on the homescreen and not doing housekeeping.
-     */
-    protected void onInteractionBegin() {}
-
-    void startApplicationDetailsActivity(ComponentName componentName) {
-        String packageName = componentName.getPackageName();
-        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
-                Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        startActivitySafely(null, intent, "startApplicationDetailsActivity");
-    }
-
-    // returns true if the activity was started
-    boolean startApplicationUninstallActivity(ComponentName componentName, int flags) {
-        if ((flags & AppInfo.DOWNLOADED_FLAG) == 0) {
-            // System applications cannot be installed. For now, show a toast explaining that.
-            // We may give them the option of disabling apps this way.
-            int messageId = R.string.uninstall_system_app_text;
-            Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show();
-            return false;
+    protected void onClickAllAppsButton(View v) {
+        if (LOGD) Log.d(TAG, "onClickAllAppsButton");
+        if (isAllAppsVisible()) {
+            showWorkspace(true);
         } else {
-            String packageName = componentName.getPackageName();
-            String className = componentName.getClassName();
-            Intent intent = new Intent(
-                    Intent.ACTION_DELETE, Uri.fromParts("package", packageName, className));
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                    Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            startActivity(intent);
-            return true;
+            showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
         }
     }
 
-    boolean startActivity(View v, Intent intent, Object tag) {
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    private void showBrokenAppInstallDialog(final String packageName,
+            DialogInterface.OnClickListener onSearchClickListener) {
+        new AlertDialog.Builder(new ContextThemeWrapper(this, android.R.style.Theme_DeviceDefault))
+            .setTitle(R.string.abandoned_promises_title)
+            .setMessage(R.string.abandoned_promise_explanation)
+            .setPositiveButton(R.string.abandoned_search, onSearchClickListener)
+            .setNeutralButton(R.string.abandoned_clean_this,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        final UserHandleCompat user = UserHandleCompat.myUserHandle();
+                        mWorkspace.removeAbandonedPromise(packageName, user);
+                    }
+                })
+            .create().show();
+        return;
+    }
 
-        try {
-            // Only launch using the new animation if the shortcut has not opted out (this is a
-            // private contract between launcher and may be ignored in the future).
-            boolean useLaunchAnimation = (v != null) &&
-                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
-            if (useLaunchAnimation) {
-                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
-                        v.getMeasuredWidth(), v.getMeasuredHeight());
+    /**
+     * Event handler for an app shortcut click.
+     *
+     * @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
+     */
+    protected void onClickAppShortcut(final View v) {
+        if (LOGD) Log.d(TAG, "onClickAppShortcut");
+        Object tag = v.getTag();
+        if (!(tag instanceof ShortcutInfo)) {
+            throw new IllegalArgumentException("Input must be a Shortcut");
+        }
 
-                startActivity(intent, opts.toBundle());
-            } else {
-                startActivity(intent);
+        // Open shortcut
+        final ShortcutInfo shortcut = (ShortcutInfo) tag;
+        final Intent intent = shortcut.intent;
+
+        // Check for special shortcuts
+        if (intent.getComponent() != null) {
+            final String shortcutClass = intent.getComponent().getClassName();
+
+            if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
+                MemoryDumpActivity.startDump(this);
+                return;
+            } else if (shortcutClass.equals(ToggleWeightWatcher.class.getName())) {
+                toggleShowWeightWatcher();
+                return;
             }
-            return true;
-        } catch (SecurityException e) {
-            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
-                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
-                    "or use the exported attribute for this activity. "
-                    + "tag="+ tag + " intent=" + intent, e);
         }
-        return false;
+
+        // Check for abandoned promise
+        if ((v instanceof BubbleTextView)
+                && shortcut.isPromise()
+                && !shortcut.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE)) {
+            showBrokenAppInstallDialog(
+                    shortcut.getTargetComponent().getPackageName(),
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int id) {
+                            startAppShortcutOrInfoActivity(v);
+                        }
+                    });
+            return;
+        }
+
+        // Start activities
+        startAppShortcutOrInfoActivity(v);
     }
 
-    boolean startActivitySafely(View v, Intent intent, Object tag) {
-        boolean success = false;
-        try {
-            success = startActivity(v, intent, tag);
-        } catch (ActivityNotFoundException e) {
-            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
+    private void startAppShortcutOrInfoActivity(View v) {
+        Object tag = v.getTag();
+        final ShortcutInfo shortcut;
+        final Intent intent;
+        if (tag instanceof ShortcutInfo) {
+            shortcut = (ShortcutInfo) tag;
+            intent = shortcut.intent;
+            int[] pos = new int[2];
+            v.getLocationOnScreen(pos);
+            intent.setSourceBounds(new Rect(pos[0], pos[1],
+                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+
+        } else if (tag instanceof AppInfo) {
+            shortcut = null;
+            intent = ((AppInfo) tag).intent;
+        } else {
+            throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
         }
-        return success;
+
+        boolean success = startActivitySafely(v, intent, tag);
+        mStats.recordLaunch(intent, shortcut);
+
+        if (success && v instanceof BubbleTextView) {
+            mWaitingForResume = (BubbleTextView) v;
+            mWaitingForResume.setStayPressed(true);
+        }
     }
 
-    private void handleFolderClick(FolderIcon folderIcon) {
+    /**
+     * Event handler for a folder icon click.
+     *
+     * @param v The view that was clicked. Must be an instance of {@link FolderIcon}.
+     */
+    protected void onClickFolderIcon(View v) {
+        if (LOGD) Log.d(TAG, "onClickFolder");
+        if (!(v instanceof FolderIcon)){
+            throw new IllegalArgumentException("Input must be a FolderIcon");
+        }
+
+        FolderIcon folderIcon = (FolderIcon) v;
         final FolderInfo info = folderIcon.getFolderInfo();
         Folder openFolder = mWorkspace.getFolderForTag(info);
 
@@ -2597,6 +2700,175 @@
     }
 
     /**
+     * Event handler for the (Add) Widgets button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickAddWidgetButton(View view) {
+        if (LOGD) Log.d(TAG, "onClickAddWidgetButton");
+        showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+    }
+
+    /**
+     * Event handler for the wallpaper picker button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickWallpaperPicker(View v) {
+        if (LOGD) Log.d(TAG, "onClickWallpaperPicker");
+        final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
+        pickWallpaper.setComponent(getWallpaperPickerComponent());
+        startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
+    }
+
+    /**
+     * Event handler for a click on the settings button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickSettingsButton(View v) {
+        if (LOGD) Log.d(TAG, "onClickSettingsButton");
+    }
+
+    public void onTouchDownAllAppsButton(View v) {
+        // Provide the same haptic feedback that the system offers for virtual keys.
+        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+    }
+
+    public void performHapticFeedbackOnTouchDown(View v) {
+        // Provide the same haptic feedback that the system offers for virtual keys.
+        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+    }
+
+    public View.OnTouchListener getHapticFeedbackTouchListener() {
+        if (mHapticFeedbackTouchListener == null) {
+            mHapticFeedbackTouchListener = new View.OnTouchListener() {
+                @Override
+                public boolean onTouch(View v, MotionEvent event) {
+                    if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
+                        v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+                    }
+                    return false;
+                }
+            };
+        }
+        return mHapticFeedbackTouchListener;
+    }
+
+    public void onDragStarted(View view) {}
+
+    /**
+     * Called when the user stops interacting with the launcher.
+     * This implies that the user is now on the homescreen and is not doing housekeeping.
+     */
+    protected void onInteractionEnd() {}
+
+    /**
+     * Called when the user starts interacting with the launcher.
+     * The possible interactions are:
+     *  - open all apps
+     *  - reorder an app shortcut, or a widget
+     *  - open the overview mode.
+     * This is a good time to stop doing things that only make sense
+     * when the user is on the homescreen and not doing housekeeping.
+     */
+    protected void onInteractionBegin() {}
+
+    void startApplicationDetailsActivity(ComponentName componentName, UserHandleCompat user) {
+        String packageName = componentName.getPackageName();
+        try {
+            LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
+            UserManagerCompat userManager = UserManagerCompat.getInstance(this);
+            launcherApps.showAppDetailsForProfile(componentName, user);
+        } catch (SecurityException e) {
+            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+            Log.e(TAG, "Launcher does not have permission to launch settings");
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+            Log.e(TAG, "Unable to launch settings");
+        }
+    }
+
+    // returns true if the activity was started
+    boolean startApplicationUninstallActivity(ComponentName componentName, int flags,
+            UserHandleCompat user) {
+        if ((flags & AppInfo.DOWNLOADED_FLAG) == 0) {
+            // System applications cannot be installed. For now, show a toast explaining that.
+            // We may give them the option of disabling apps this way.
+            int messageId = R.string.uninstall_system_app_text;
+            Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show();
+            return false;
+        } else {
+            String packageName = componentName.getPackageName();
+            String className = componentName.getClassName();
+            Intent intent = new Intent(
+                    Intent.ACTION_DELETE, Uri.fromParts("package", packageName, className));
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                    Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            if (user != null) {
+                user.addToIntent(intent, Intent.EXTRA_USER);
+            }
+            startActivity(intent);
+            return true;
+        }
+    }
+
+    boolean startActivity(View v, Intent intent, Object tag) {
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        try {
+            // Only launch using the new animation if the shortcut has not opted out (this is a
+            // private contract between launcher and may be ignored in the future).
+            boolean useLaunchAnimation = (v != null) &&
+                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
+            LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
+            UserManagerCompat userManager = UserManagerCompat.getInstance(this);
+
+            UserHandleCompat user = null;
+            if (intent.hasExtra(AppInfo.EXTRA_PROFILE)) {
+                long serialNumber = intent.getLongExtra(AppInfo.EXTRA_PROFILE, -1);
+                user = userManager.getUserForSerialNumber(serialNumber);
+            }
+
+            Bundle optsBundle = null;
+            if (useLaunchAnimation) {
+                ActivityOptions opts = Utilities.isLmpOrAbove() ?
+                        ActivityOptions.makeCustomAnimation(this, R.anim.task_open_enter, R.anim.no_anim) :
+                        ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
+                optsBundle = opts.toBundle();
+            }
+
+            if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
+                // Could be launching some bookkeeping activity
+                startActivity(intent, optsBundle);
+            } else {
+                // TODO Component can be null when shortcuts are supported for secondary user
+                launcherApps.startActivityForProfile(intent.getComponent(), user,
+                        intent.getSourceBounds(), optsBundle);
+            }
+            return true;
+        } catch (SecurityException e) {
+            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
+                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
+                    "or use the exported attribute for this activity. "
+                    + "tag="+ tag + " intent=" + intent, e);
+        }
+        return false;
+    }
+
+    boolean startActivitySafely(View v, Intent intent, Object tag) {
+        boolean success = false;
+        if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
+            Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
+            return false;
+        }
+        try {
+            success = startActivity(v, intent, tag);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
+        }
+        return success;
+    }
+
+    /**
      * This method draws the FolderIcon to an ImageView and then adds and positions that ImageView
      * in the DragLayer in the exact absolute location of the original FolderIcon.
      */
@@ -2667,7 +2939,10 @@
 
         ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha,
                 scaleX, scaleY);
-        oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+        if (Utilities.isLmpOrAbove()) {
+            oa.setInterpolator(new LogDecelerateInterpolator(100, 0));
+        }
+        oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
         oa.start();
     }
 
@@ -2684,7 +2959,7 @@
         copyFolderIconToImage(fi);
         ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha,
                 scaleX, scaleY);
-        oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+        oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -2737,9 +3012,6 @@
                 folder.dismissEditingName();
             }
             closeFolder(folder);
-
-            // Dismiss the folder cling
-            mLauncherClings.dismissFolderCling(null);
         }
     }
 
@@ -2772,37 +3044,40 @@
                 } else {
                     return false;
                 }
+            } else {
+                return false;
             }
         }
 
-        if (!(v instanceof CellLayout)) {
-            v = (View) v.getParent().getParent();
-        }
-
-        resetAddInfo();
-        CellLayout.CellInfo longClickCellInfo = (CellLayout.CellInfo) v.getTag();
-        // This happens when long clicking an item with the dpad/trackball
-        if (longClickCellInfo == null) {
-            return true;
+        CellLayout.CellInfo longClickCellInfo = null;
+        View itemUnderLongClick = null;
+        if (v.getTag() instanceof ItemInfo) {
+            ItemInfo info = (ItemInfo) v.getTag();
+            longClickCellInfo = new CellLayout.CellInfo(v, info);;
+            itemUnderLongClick = longClickCellInfo.cell;
+            resetAddInfo();
         }
 
         // The hotseat touch handling does not go through Workspace, and we always allow long press
         // on hotseat items.
-        final View itemUnderLongClick = longClickCellInfo.cell;
-        boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();
+        final boolean inHotseat = isHotseatLayout(v);
+        boolean allowLongPress = inHotseat || mWorkspace.allowLongPress();
         if (allowLongPress && !mDragController.isDragging()) {
             if (itemUnderLongClick == null) {
                 // User long pressed on empty space
                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-                // Disabling reordering until we sort out some issues.
                 if (mWorkspace.isInOverviewMode()) {
                     mWorkspace.startReordering(v);
                 } else {
                     mWorkspace.enterOverviewMode();
                 }
             } else {
-                if (!(itemUnderLongClick instanceof Folder)) {
+                final boolean isAllAppsButton = inHotseat && isAllAppsButtonRank(
+                        mHotseat.getOrderInHotseat(
+                                longClickCellInfo.cellX,
+                                longClickCellInfo.cellY));
+                if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) {
                     // User long pressed on an item
                     mWorkspace.startDrag(longClickCellInfo);
                 }
@@ -2835,22 +3110,12 @@
         return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE);
     }
 
-    /**
-     * Helper method for the cameraZoomIn/cameraZoomOut animations
-     * @param view The view being animated
-     * @param scaleFactor The scale factor used for the zoom
-     */
-    private void setPivotsForZoom(View view, float scaleFactor) {
-        view.setPivotX(view.getWidth() / 2.0f);
-        view.setPivotY(view.getHeight() / 2.0f);
-    }
-
     private void setWorkspaceBackground(boolean workspace) {
         mLauncherView.setBackground(workspace ?
                 mWorkspaceBackgroundDrawable : null);
     }
 
-    void updateWallpaperVisibility(boolean visible) {
+    protected void changeWallpaperVisiblity(boolean visible) {
         int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
         int curflags = getWindow().getAttributes().flags
                 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -2939,6 +3204,7 @@
         AppsCustomizePagedView.ContentType contentType = mAppsCustomizeContent.getContentType();
         showAppsCustomizeHelper(animated, springLoaded, contentType);
     }
+
     private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded,
                                          final AppsCustomizePagedView.ContentType contentType) {
         if (mStateAnimation != null) {
@@ -2946,98 +3212,178 @@
             mStateAnimation.cancel();
             mStateAnimation = null;
         }
+
+        boolean material = Utilities.isLmpOrAbove();
+
         final Resources res = getResources();
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
         final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
+        final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
+        final int itemsAlphaStagger =
+                res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
+
         final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
         final View fromView = mWorkspace;
         final AppsCustomizeTabHost toView = mAppsCustomizeTabHost;
-        final int startDelay =
-                res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
 
-        setPivotsForZoom(toView, scale);
+        final ArrayList<View> layerViews = new ArrayList<View>();
 
-        // Shrink workspaces away if going to AppsCustomize from workspace
+        Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ?
+                Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN;
         Animator workspaceAnim =
-                mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated);
+                mWorkspace.getChangeStateAnimation(workspaceState, animated, layerViews);
         if (!LauncherAppState.isDisableAllApps()
                 || contentType == AppsCustomizePagedView.ContentType.Widgets) {
             // Set the content type for the all apps/widgets space
             mAppsCustomizeTabHost.setContentTypeImmediate(contentType);
         }
 
-        if (animated) {
-            toView.setScaleX(scale);
-            toView.setScaleY(scale);
-            final LauncherViewPropertyAnimator scaleAnim = new LauncherViewPropertyAnimator(toView);
-            scaleAnim.
-                scaleX(1f).scaleY(1f).
-                setDuration(duration).
-                setInterpolator(new Workspace.ZoomOutInterpolator());
+        // If for some reason our views aren't initialized, don't animate
+        boolean initialized = getAllAppsButton() != null;
 
-            toView.setVisibility(View.VISIBLE);
-            toView.setAlpha(0f);
-            final ObjectAnimator alphaAnim = LauncherAnimUtils
-                .ofFloat(toView, "alpha", 0f, 1f)
-                .setDuration(fadeDuration);
-            alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
-            alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    if (animation == null) {
-                        throw new RuntimeException("animation is null");
-                    }
-                    float t = (Float) animation.getAnimatedValue();
-                    dispatchOnLauncherTransitionStep(fromView, t);
-                    dispatchOnLauncherTransitionStep(toView, t);
-                }
-            });
-
-            // toView should appear right at the end of the workspace shrink
-            // animation
+        if (animated && initialized) {
             mStateAnimation = LauncherAnimUtils.createAnimatorSet();
-            mStateAnimation.play(scaleAnim).after(startDelay);
-            mStateAnimation.play(alphaAnim).after(startDelay);
+            final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                    toView.findViewById(R.id.apps_customize_pane_content);
+
+            final View page = content.getPageAt(content.getCurrentPage());
+            final View revealView = toView.findViewById(R.id.fake_page);
+
+            final float initialPanelAlpha = 1f;
+
+            final boolean isWidgetTray = contentType == AppsCustomizePagedView.ContentType.Widgets;
+            if (isWidgetTray) {
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
+            } else {
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
+            }
+
+            // Hide the real page background, and swap in the fake one
+            content.setPageBackgroundsVisible(false);
+            revealView.setVisibility(View.VISIBLE);
+            // We need to hide this view as the animation start will be posted.
+            revealView.setAlpha(0);
+
+            int width = revealView.getMeasuredWidth();
+            int height = revealView.getMeasuredHeight();
+            float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
+
+            revealView.setTranslationY(0);
+            revealView.setTranslationX(0);
+
+            // Get the y delta between the center of the page and the center of the all apps button
+            int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+                    getAllAppsButton(), null);
+
+            float alpha = 0;
+            float xDrift = 0;
+            float yDrift = 0;
+            if (material) {
+                alpha = isWidgetTray ? 0.3f : 1f;
+                yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
+                xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
+            } else {
+                yDrift = 2 * height / 3;
+                xDrift = 0;
+            }
+            final float initAlpha = alpha;
+
+            revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            layerViews.add(revealView);
+            PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", initAlpha, 1f);
+            PropertyValuesHolder panelDriftY =
+                    PropertyValuesHolder.ofFloat("translationY", yDrift, 0);
+            PropertyValuesHolder panelDriftX =
+                    PropertyValuesHolder.ofFloat("translationX", xDrift, 0);
+
+            ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
+                    panelAlpha, panelDriftY, panelDriftX);
+
+            panelAlphaAndDrift.setDuration(revealDuration);
+            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+
+            mStateAnimation.play(panelAlphaAndDrift);
+
+            if (page != null) {
+                page.setVisibility(View.VISIBLE);
+                page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                layerViews.add(page);
+
+                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0);
+                page.setTranslationY(yDrift);
+                pageDrift.setDuration(revealDuration);
+                pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                pageDrift.setStartDelay(itemsAlphaStagger);
+                mStateAnimation.play(pageDrift);
+
+                page.setAlpha(0f);
+                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, "alpha", 0f, 1f);
+                itemsAlpha.setDuration(revealDuration);
+                itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+                itemsAlpha.setStartDelay(itemsAlphaStagger);
+                mStateAnimation.play(itemsAlpha);
+            }
+
+            View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator);
+            pageIndicators.setAlpha(0.01f);
+            ObjectAnimator indicatorsAlpha =
+                    ObjectAnimator.ofFloat(pageIndicators, "alpha", 1f);
+            indicatorsAlpha.setDuration(revealDuration);
+            mStateAnimation.play(indicatorsAlpha);
+
+            if (material) {
+                final View allApps = getAllAppsButton();
+                int allAppsButtonSize = LauncherAppState.getInstance().
+                        getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
+                float startRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
+                Animator reveal = ViewAnimationUtils.createCircularReveal(revealView, width / 2,
+                                height / 2, startRadius, revealRadius);
+                reveal.setDuration(revealDuration);
+                reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+
+                reveal.addListener(new AnimatorListenerAdapter() {
+                    public void onAnimationStart(Animator animation) {
+                        if (!isWidgetTray) {
+                            allApps.setVisibility(View.INVISIBLE);
+                        }
+                    }
+                    public void onAnimationEnd(Animator animation) {
+                        if (!isWidgetTray) {
+                            allApps.setVisibility(View.VISIBLE);
+                        }
+                    }
+                });
+                mStateAnimation.play(reveal);
+            }
 
             mStateAnimation.addListener(new AnimatorListenerAdapter() {
                 @Override
-                public void onAnimationStart(Animator animation) {
-                    // Prepare the position
-                    toView.setTranslationX(0.0f);
-                    toView.setTranslationY(0.0f);
-                    toView.setVisibility(View.VISIBLE);
-                    toView.bringToFront();
-                }
-                @Override
                 public void onAnimationEnd(Animator animation) {
                     dispatchOnLauncherTransitionEnd(fromView, animated, false);
                     dispatchOnLauncherTransitionEnd(toView, animated, false);
 
+                    revealView.setVisibility(View.INVISIBLE);
+                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
+                    if (page != null) {
+                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+                    }
+                    content.setPageBackgroundsVisible(true);
+
                     // Hide the search bar
                     if (mSearchDropTargetBar != null) {
                         mSearchDropTargetBar.hideSearchBar(false);
                     }
                 }
+
             });
 
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
             }
 
-            boolean delayAnim = false;
-
             dispatchOnLauncherTransitionPrepare(fromView, animated, false);
             dispatchOnLauncherTransitionPrepare(toView, animated, false);
-
-            // If any of the objects being animated haven't been measured/laid out
-            // yet, delay the animation until we get a layout pass
-            if ((((LauncherTransitionable) toView).getContent().getMeasuredWidth() == 0) ||
-                    (mWorkspace.getMeasuredWidth() == 0) ||
-                    (toView.getMeasuredWidth() == 0)) {
-                delayAnim = true;
-            }
-
             final AnimatorSet stateAnimation = mStateAnimation;
             final Runnable startAnimRunnable = new Runnable() {
                 public void run() {
@@ -3045,23 +3391,28 @@
                     // we waited for a layout/draw pass
                     if (mStateAnimation != stateAnimation)
                         return;
-                    setPivotsForZoom(toView, scale);
                     dispatchOnLauncherTransitionStart(fromView, animated, false);
                     dispatchOnLauncherTransitionStart(toView, animated, false);
-                    LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView);
+
+                    revealView.setAlpha(initAlpha);
+                    if (Utilities.isLmpOrAbove()) {
+                        for (int i = 0; i < layerViews.size(); i++) {
+                            View v = layerViews.get(i);
+                            if (v != null) {
+                                boolean attached = true;
+                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                                    attached = v.isAttachedToWindow();
+                                }
+                                if (attached) v.buildLayer();
+                            }
+                        }
+                    }
+                    mStateAnimation.start();
                 }
             };
-            if (delayAnim) {
-                final ViewTreeObserver observer = toView.getViewTreeObserver();
-                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-                        public void onGlobalLayout() {
-                            startAnimRunnable.run();
-                            toView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                        }
-                    });
-            } else {
-                startAnimRunnable.run();
-            }
+            toView.bringToFront();
+            toView.setVisibility(View.VISIBLE);
+            toView.post(startAnimRunnable);
         } else {
             toView.setTranslationX(0.0f);
             toView.setTranslationY(0.0f);
@@ -3098,54 +3449,184 @@
             mStateAnimation.cancel();
             mStateAnimation = null;
         }
+
+        boolean material = Utilities.isLmpOrAbove();
         Resources res = getResources();
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
-        final int fadeOutDuration =
-                res.getInteger(R.integer.config_appsCustomizeFadeOutTime);
+        final int fadeOutDuration = res.getInteger(R.integer.config_appsCustomizeFadeOutTime);
+        final int revealDuration = res.getInteger(R.integer.config_appsCustomizeConcealTime);
+        final int itemsAlphaStagger =
+                res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
+
         final float scaleFactor = (float)
                 res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
         final View fromView = mAppsCustomizeTabHost;
         final View toView = mWorkspace;
         Animator workspaceAnim = null;
+        final ArrayList<View> layerViews = new ArrayList<View>();
+
         if (toState == Workspace.State.NORMAL) {
-            int stagger = res.getInteger(R.integer.config_appsCustomizeWorkspaceAnimationStagger);
             workspaceAnim = mWorkspace.getChangeStateAnimation(
-                    toState, animated, stagger, -1);
+                    toState, animated, layerViews);
         } else if (toState == Workspace.State.SPRING_LOADED ||
                 toState == Workspace.State.OVERVIEW) {
             workspaceAnim = mWorkspace.getChangeStateAnimation(
-                    toState, animated);
+                    toState, animated, layerViews);
         }
 
-        setPivotsForZoom(fromView, scaleFactor);
-        showHotseat(animated);
-        if (animated) {
-            final LauncherViewPropertyAnimator scaleAnim =
-                    new LauncherViewPropertyAnimator(fromView);
-            scaleAnim.
-                scaleX(scaleFactor).scaleY(scaleFactor).
-                setDuration(duration).
-                setInterpolator(new Workspace.ZoomInInterpolator());
+        // If for some reason our views aren't initialized, don't animate
+        boolean initialized = getAllAppsButton() != null;
 
-            final ObjectAnimator alphaAnim = LauncherAnimUtils
-                .ofFloat(fromView, "alpha", 1f, 0f)
-                .setDuration(fadeOutDuration);
-            alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator());
-            alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    float t = 1f - (Float) animation.getAnimatedValue();
-                    dispatchOnLauncherTransitionStep(fromView, t);
-                    dispatchOnLauncherTransitionStep(toView, t);
-                }
-            });
-
+        if (animated && initialized) {
             mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+            if (workspaceAnim != null) {
+                mStateAnimation.play(workspaceAnim);
+            }
 
-            dispatchOnLauncherTransitionPrepare(fromView, animated, true);
-            dispatchOnLauncherTransitionPrepare(toView, animated, true);
-            mAppsCustomizeContent.stopScrolling();
+            final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                    fromView.findViewById(R.id.apps_customize_pane_content);
+
+            final View page = content.getPageAt(content.getNextPage());
+
+            // We need to hide side pages of the Apps / Widget tray to avoid some ugly edge cases
+            int count = content.getChildCount();
+            for (int i = 0; i < count; i++) {
+                View child = content.getChildAt(i);
+                if (child != page) {
+                    child.setVisibility(View.INVISIBLE);
+                }
+            }
+            final View revealView = fromView.findViewById(R.id.fake_page);
+
+            // hideAppsCustomizeHelper is called in some cases when it is already hidden
+            // don't perform all these no-op animations. In particularly, this was causing
+            // the all-apps button to pop in and out.
+            if (fromView.getVisibility() == View.VISIBLE) {
+                AppsCustomizePagedView.ContentType contentType = content.getContentType();
+                final boolean isWidgetTray =
+                        contentType == AppsCustomizePagedView.ContentType.Widgets;
+
+                if (isWidgetTray) {
+                    revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
+                } else {
+                    revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
+                }
+
+                int width = revealView.getMeasuredWidth();
+                int height = revealView.getMeasuredHeight();
+                float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
+
+                // Hide the real page background, and swap in the fake one
+                revealView.setVisibility(View.VISIBLE);
+                content.setPageBackgroundsVisible(false);
+
+                final View allAppsButton = getAllAppsButton();
+                revealView.setTranslationY(0);
+                int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+                        allAppsButton, null);
+
+                float xDrift = 0;
+                float yDrift = 0;
+                if (material) {
+                    yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
+                    xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
+                } else {
+                    yDrift = 5 * height / 4;
+                    xDrift = 0;
+                }
+
+                revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                TimeInterpolator decelerateInterpolator = material ?
+                        new LogDecelerateInterpolator(100, 0) :
+                        new LogDecelerateInterpolator(30, 0);
+
+                // The vertical motion of the apps panel should be delayed by one frame
+                // from the conceal animation in order to give the right feel. We correpsondingly
+                // shorten the duration so that the slide and conceal end at the same time.
+                ObjectAnimator panelDriftY = LauncherAnimUtils.ofFloat(revealView, "translationY",
+                        0, yDrift);
+                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                panelDriftY.setInterpolator(decelerateInterpolator);
+                mStateAnimation.play(panelDriftY);
+
+                ObjectAnimator panelDriftX = LauncherAnimUtils.ofFloat(revealView, "translationX",
+                        0, xDrift);
+                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                panelDriftX.setInterpolator(decelerateInterpolator);
+                mStateAnimation.play(panelDriftX);
+
+                if (isWidgetTray || !material) {
+                    float finalAlpha = material ? 0.4f : 0f;
+                    revealView.setAlpha(1f);
+                    ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha",
+                            1f, finalAlpha);
+                    panelAlpha.setDuration(revealDuration);
+                    panelAlpha.setInterpolator(material ? decelerateInterpolator :
+                        new AccelerateInterpolator(1.5f));
+                    mStateAnimation.play(panelAlpha);
+                }
+
+                if (page != null) {
+                    page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+                    ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
+                            0, yDrift);
+                    page.setTranslationY(0);
+                    pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                    pageDrift.setInterpolator(decelerateInterpolator);
+                    pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                    mStateAnimation.play(pageDrift);
+
+                    page.setAlpha(1f);
+                    ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 1f, 0f);
+                    itemsAlpha.setDuration(100);
+                    itemsAlpha.setInterpolator(decelerateInterpolator);
+                    mStateAnimation.play(itemsAlpha);
+                }
+
+                View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
+                pageIndicators.setAlpha(1f);
+                ObjectAnimator indicatorsAlpha =
+                        LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 0f);
+                indicatorsAlpha.setDuration(revealDuration);
+                indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
+                mStateAnimation.play(indicatorsAlpha);
+
+                width = revealView.getMeasuredWidth();
+
+                if (material) {
+                    if (!isWidgetTray) {
+                        allAppsButton.setVisibility(View.INVISIBLE);
+                    }
+                    int allAppsButtonSize = LauncherAppState.getInstance().
+                            getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
+                    float finalRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
+                    Animator reveal =
+                            LauncherAnimUtils.createCircularReveal(revealView, width / 2,
+                                    height / 2, revealRadius, finalRadius);
+                    reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                    reveal.setDuration(revealDuration);
+                    reveal.setStartDelay(itemsAlphaStagger);
+
+                    reveal.addListener(new AnimatorListenerAdapter() {
+                        public void onAnimationEnd(Animator animation) {
+                            revealView.setVisibility(View.INVISIBLE);
+                            if (!isWidgetTray) {
+                                allAppsButton.setVisibility(View.VISIBLE);
+                            }
+                        }
+                    });
+
+                    mStateAnimation.play(reveal);
+                }
+
+                dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+                dispatchOnLauncherTransitionPrepare(toView, animated, true);
+                mAppsCustomizeContent.stopScrolling();
+            }
 
             mStateAnimation.addListener(new AnimatorListenerAdapter() {
                 @Override
@@ -3156,17 +3637,57 @@
                     if (onCompleteRunnable != null) {
                         onCompleteRunnable.run();
                     }
+
+                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
+                    if (page != null) {
+                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+                    }
+                    content.setPageBackgroundsVisible(true);
+                    // Unhide side pages
+                    int count = content.getChildCount();
+                    for (int i = 0; i < count; i++) {
+                        View child = content.getChildAt(i);
+                        child.setVisibility(View.VISIBLE);
+                    }
+
+                    // Reset page transforms
+                    if (page != null) {
+                        page.setTranslationX(0);
+                        page.setTranslationY(0);
+                        page.setAlpha(1);
+                    }
+                    content.setCurrentPage(content.getNextPage());
+
                     mAppsCustomizeContent.updateCurrentPageScroll();
                 }
             });
 
-            mStateAnimation.playTogether(scaleAnim, alphaAnim);
-            if (workspaceAnim != null) {
-                mStateAnimation.play(workspaceAnim);
-            }
-            dispatchOnLauncherTransitionStart(fromView, animated, true);
-            dispatchOnLauncherTransitionStart(toView, animated, true);
-            LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView);
+            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;
+                    dispatchOnLauncherTransitionStart(fromView, animated, false);
+                    dispatchOnLauncherTransitionStart(toView, animated, false);
+
+                    if (Utilities.isLmpOrAbove()) {
+                        for (int i = 0; i < layerViews.size(); i++) {
+                            View v = layerViews.get(i);
+                            if (v != null) {
+                                boolean attached = true;
+                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                                    attached = v.isAttachedToWindow();
+                                }
+                                if (attached) v.buildLayer();
+                            }
+                        }
+                    }
+                    mStateAnimation.start();
+                }
+            };
+            fromView.post(startAnimRunnable);
         } else {
             fromView.setVisibility(View.GONE);
             dispatchOnLauncherTransitionPrepare(fromView, animated, true);
@@ -3195,10 +3716,7 @@
     }
 
     void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
-        if (mWorkspace.isInOverviewMode()) {
-            mWorkspace.exitOverviewMode(animated);
-        }
-        if (mState != State.WORKSPACE) {
+        if (mState != State.WORKSPACE || mWorkspace.getState() != Workspace.State.NORMAL) {
             boolean wasInSpringLoadedMode = (mState != State.WORKSPACE);
             mWorkspace.setVisibility(View.VISIBLE);
             hideAppsCustomizeHelper(Workspace.State.NORMAL, animated, false, onCompleteRunnable);
@@ -3247,7 +3765,13 @@
             mAppsCustomizeTabHost.reset();
         }
         showAppsCustomizeHelper(animated, false, contentType);
-        mAppsCustomizeTabHost.requestFocus();
+        mAppsCustomizeTabHost.post(new Runnable() {
+            @Override
+            public void run() {
+                // We post this in-case the all apps view isn't yet constructed.
+                mAppsCustomizeTabHost.requestFocus();
+            }
+        });
 
         // Change the state *after* we've called all the transition code
         mState = State.APPS_CUSTOMIZE;
@@ -3287,7 +3811,6 @@
                 }
             }
         }, delay);
-
     }
 
     void exitSpringLoadedDragMode() {
@@ -3309,25 +3832,6 @@
     }
 
     /**
-     * Shows the hotseat area.
-     */
-    void showHotseat(boolean animated) {
-        if (!LauncherAppState.getInstance().isScreenLarge()) {
-            if (animated) {
-                if (mHotseat.getAlpha() != 1f) {
-                    int duration = 0;
-                    if (mSearchDropTargetBar != null) {
-                        duration = mSearchDropTargetBar.getTransitionInDuration();
-                    }
-                    mHotseat.animate().alpha(1f).setDuration(duration);
-                }
-            } else {
-                mHotseat.setAlpha(1f);
-            }
-        }
-    }
-
-    /**
      * Hides the hotseat area.
      */
     void hideHotseat(boolean animated) {
@@ -3461,11 +3965,11 @@
     }
 
     public View getQsbBar() {
-        if (mQsbBar == null) {
-            mQsbBar = mInflater.inflate(R.layout.search_bar, mSearchDropTargetBar, false);
-            mSearchDropTargetBar.addView(mQsbBar);
+        if (mQsb == null) {
+            mQsb = mInflater.inflate(R.layout.qsb, mSearchDropTargetBar, false);
+            mSearchDropTargetBar.addView(mQsb);
         }
-        return mQsbBar;
+        return mQsb;
     }
 
     protected boolean updateGlobalSearchIcon() {
@@ -3580,44 +4084,6 @@
     public void disableVoiceButtonProxy(boolean disabled) {
         updateVoiceButtonProxyVisible(disabled);
     }
-    /**
-     * Sets the app market icon
-     */
-    private void updateAppMarketIcon() {
-        if (!DISABLE_MARKET_BUTTON) {
-            final View marketButton = findViewById(R.id.market_button);
-            Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
-            // Find the app market activity by resolving an intent.
-            // (If multiple app markets are installed, it will return the ResolverActivity.)
-            ComponentName activityName = intent.resolveActivity(getPackageManager());
-            if (activityName != null) {
-                int coi = getCurrentOrientationIndexForGlobalIcons();
-                mAppMarketIntent = intent;
-                sAppMarketIcon[coi] = updateTextButtonWithIconFromExternalActivity(
-                        R.id.market_button, activityName, R.drawable.ic_launcher_market_holo,
-                        TOOLBAR_ICON_METADATA_NAME);
-                marketButton.setVisibility(View.VISIBLE);
-            } else {
-                // We should hide and disable the view so that we don't try and restore the visibility
-                // of it when we swap between drag & normal states from IconDropTarget subclasses.
-                marketButton.setVisibility(View.GONE);
-                marketButton.setEnabled(false);
-            }
-        }
-    }
-
-    private void updateAppMarketIcon(Drawable.ConstantState d) {
-        if (!DISABLE_MARKET_BUTTON) {
-            // Ensure that the new drawable we are creating has the approprate toolbar icon bounds
-            Resources r = getResources();
-            Drawable marketIconDrawable = d.newDrawable(r);
-            int w = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_width);
-            int h = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_height);
-            marketIconDrawable.setBounds(0, 0, w, h);
-
-            updateTextButtonWithDrawable(R.id.market_button, marketIconDrawable);
-        }
-    }
 
     @Override
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
@@ -3626,7 +4092,7 @@
         text.clear();
         // Populate event with a fake title based on the current state.
         if (mState == State.APPS_CUSTOMIZE) {
-            text.add(mAppsCustomizeTabHost.getCurrentTabView().getContentDescription());
+            text.add(mAppsCustomizeTabHost.getContentTag());
         } else {
             text.add(getString(R.string.all_apps_home_button_label));
         }
@@ -3734,6 +4200,8 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void startBinding() {
+        setWorkspaceLoading(true);
+
         // If we're starting binding all over again, clear any bind calls we'd postponed in
         // the past (see waitUntilResume) -- we don't need them since we're starting binding
         // from scratch again
@@ -3760,9 +4228,9 @@
 
         // Create the custom content page (this call updates mDefaultScreen which calls
         // setCurrentPage() so ensure that all pages are added before calling this).
-        // The actual content of the custom page will be added during onFinishBindingItems().
-        if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
-            mWorkspace.createCustomContentPage();
+        if (hasCustomContentToLeft()) {
+            mWorkspace.createCustomContentContainer();
+            populateCustomContentContainer();
         }
     }
 
@@ -3816,21 +4284,23 @@
         }
 
         // Add the new screens
-        bindAddScreens(newScreens);
+        if (newScreens != null) {
+            bindAddScreens(newScreens);
+        }
 
         // We add the items without animation on non-visible pages, and with
         // animations on the new page (which we will try and snap to).
-        if (!addNotAnimated.isEmpty()) {
+        if (addNotAnimated != null && !addNotAnimated.isEmpty()) {
             bindItems(addNotAnimated, 0,
                     addNotAnimated.size(), false);
         }
-        if (!addAnimated.isEmpty()) {
+        if (addAnimated != null && !addAnimated.isEmpty()) {
             bindItems(addAnimated, 0,
                     addAnimated.size(), true);
         }
 
         // Remove the extra empty screen
-        mWorkspace.removeExtraEmptyScreen(false, null);
+        mWorkspace.removeExtraEmptyScreen(false, false);
 
         if (!LauncherAppState.isDisableAllApps() &&
                 addedApps != null && mAppsCustomizeContent != null) {
@@ -3881,7 +4351,15 @@
                     if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                         CellLayout cl = mWorkspace.getScreenWithId(item.screenId);
                         if (cl != null && cl.isOccupied(item.cellX, item.cellY)) {
-                            throw new RuntimeException("OCCUPIED");
+                            View v = cl.getChildAt(item.cellX, item.cellY);
+                            Object tag = v.getTag();
+                            String desc = "Collision while binding workspace item: " + item
+                                    + ". Collides with " + tag;
+                            if (LauncherAppState.isDogfoodBuild()) {
+                                throw (new RuntimeException(desc));
+                            } else {
+                                Log.d(TAG, desc);
+                            }
                         }
                     }
 
@@ -3924,9 +4402,11 @@
                     // when we are loading right after we return to launcher.
                     mWorkspace.postDelayed(new Runnable() {
                         public void run() {
-                            mWorkspace.snapToPage(newScreenIndex);
-                            mWorkspace.postDelayed(startBounceAnimRunnable,
-                                    NEW_APPS_ANIMATION_DELAY);
+                            if (mWorkspace != null) {
+                                mWorkspace.snapToPage(newScreenIndex);
+                                mWorkspace.postDelayed(startBounceAnimRunnable,
+                                        NEW_APPS_ANIMATION_DELAY);
+                            }
                         }
                     }, NEW_APPS_PAGE_MOVE_DELAY);
                 } else {
@@ -3974,13 +4454,74 @@
         }
         final Workspace workspace = mWorkspace;
 
-        final int appWidgetId = item.appWidgetId;
-        final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
-        if (DEBUG_WIDGETS) {
-            Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
+        AppWidgetProviderInfo appWidgetInfo;
+        if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) &&
+                ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
+
+            appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName);
+            if (appWidgetInfo == null) {
+                if (DEBUG_WIDGETS) {
+                    Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+                            + " belongs to component " + item.providerName
+                            + ", as the povider is null");
+                }
+                LauncherModel.deleteItemFromDatabase(this, item);
+                return;
+            }
+            // Note: This assumes that the id remap broadcast is received before this step.
+            // If that is not the case, the id remap will be ignored and user may see the
+            // click to setup view.
+            PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo, null, null);
+            pendingInfo.spanX = item.spanX;
+            pendingInfo.spanY = item.spanY;
+            pendingInfo.minSpanX = item.minSpanX;
+            pendingInfo.minSpanY = item.minSpanY;
+            Bundle options =
+                    AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo);
+
+            int newWidgetId = mAppWidgetHost.allocateAppWidgetId();
+            boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
+                    newWidgetId, appWidgetInfo, options);
+
+            // TODO consider showing a permission dialog when the widget is clicked.
+            if (!success) {
+                mAppWidgetHost.deleteAppWidgetId(newWidgetId);
+                if (DEBUG_WIDGETS) {
+                    Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+                            + " belongs to component " + item.providerName
+                            + ", as the launcher is unable to bing a new widget id");
+                }
+                LauncherModel.deleteItemFromDatabase(this, item);
+                return;
+            }
+
+            item.appWidgetId = newWidgetId;
+
+            // If the widget has a configure activity, it is still needs to set it up, otherwise
+            // the widget is ready to go.
+            item.restoreStatus = (appWidgetInfo.configure == null)
+                    ? LauncherAppWidgetInfo.RESTORE_COMPLETED
+                    : LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
+
+            LauncherModel.updateItemInDatabase(this, item);
         }
 
-        item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+        if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
+            final int appWidgetId = item.appWidgetId;
+            appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+            if (DEBUG_WIDGETS) {
+                Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
+            }
+
+            item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+        } else {
+            appWidgetInfo = null;
+            PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item);
+            view.updateIcon(mIconCache);
+            item.hostView = view;
+            item.hostView.updateAppWidget(null);
+            item.hostView.setOnClickListener(this);
+        }
 
         item.hostView.setTag(item);
         item.onBindAppWidget(this);
@@ -3997,6 +4538,26 @@
         }
     }
 
+    /**
+     * Restores a pending widget.
+     *
+     * @param appWidgetId The app widget id
+     * @param cellInfo The position on screen where to create the widget.
+     */
+    private void completeRestoreAppWidget(final int appWidgetId) {
+        LauncherAppWidgetHostView view = mWorkspace.getWidgetForAppWidgetId(appWidgetId);
+        if ((view == null) || !(view instanceof PendingAppWidgetHostView)) {
+            Log.e(TAG, "Widget update called, when the widget no longer exists.");
+            return;
+        }
+
+        LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+        info.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+
+        mWorkspace.reinflateWidgetsIfNecessary();
+        LauncherModel.updateItemInDatabase(this, info);
+    }
+
     public void onPageBoundSynchronously(int page) {
         mSynchronouslyBoundPages.add(page);
     }
@@ -4024,31 +4585,44 @@
 
         mWorkspace.restoreInstanceStateForRemainingPages();
 
+        setWorkspaceLoading(false);
+        sendLoadingCompleteBroadcastIfNecessary();
+
         // If we received the result of any pending adds while the loader was running (e.g. the
         // widget configuration forced an orientation change), process them now.
-        for (int i = 0; i < sPendingAddList.size(); i++) {
-            completeAdd(sPendingAddList.get(i));
-        }
-        sPendingAddList.clear();
+        if (sPendingAddItem != null) {
+            final long screenId = completeAdd(sPendingAddItem);
 
-        // Update the market app icon as necessary (the other icons will be managed in response to
-        // package changes in bindSearchablesChanged()
-        if (!DISABLE_MARKET_BUTTON) {
-            updateAppMarketIcon();
+            // TODO: this moves the user to the page where the pending item was added. Ideally,
+            // the screen would be guaranteed to exist after bind, and the page would be set through
+            // the workspace restore process.
+            mWorkspace.post(new Runnable() {
+                @Override
+                public void run() {
+                    mWorkspace.snapToScreenId(screenId);
+                }
+            });
+            sPendingAddItem = null;
         }
 
-        mWorkspaceLoading = false;
         if (upgradePath) {
             mWorkspace.getUniqueComponents(true, null);
             mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
         }
+        PackageInstallerCompat.getInstance(this).onFinishBind();
+        mModel.recheckRestoredItems(this);
+    }
 
-        mWorkspace.post(new Runnable() {
-            @Override
-            public void run() {
-                onFinishBindingItems();
-            }
-        });
+    private void sendLoadingCompleteBroadcastIfNecessary() {
+        if (!mSharedPrefs.getBoolean(FIRST_LOAD_COMPLETE, false)) {
+            String permission =
+                    getResources().getString(R.string.receive_first_load_broadcast_permission);
+            Intent intent = new Intent(ACTION_FIRST_LOAD_COMPLETE);
+            sendBroadcast(intent, permission);
+            SharedPreferences.Editor editor = mSharedPrefs.edit();
+            editor.putBoolean(FIRST_LOAD_COMPLETE, true);
+            editor.apply();
+        }
     }
 
     public boolean isAllAppsButtonRank(int rank) {
@@ -4136,7 +4710,7 @@
         }
 
         if (mWorkspace != null) {
-            mWorkspace.updateShortcuts(apps);
+            mWorkspace.updateShortcutsAndWidgets(apps);
         }
 
         if (!LauncherAppState.isDisableAllApps() &&
@@ -4146,6 +4720,48 @@
     }
 
     /**
+     * Packages were restored
+     */
+    public void bindAppsRestored(final ArrayList<AppInfo> apps) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindAppsRestored(apps);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
+        }
+
+        if (mWorkspace != null) {
+            mWorkspace.updateShortcutsAndWidgets(apps);
+        }
+    }
+
+    /**
+     * Update the state of a package, typically related to install state.
+     *
+     * Implementation of the method from LauncherModel.Callbacks.
+     */
+    @Override
+    public void updatePackageState(ArrayList<PackageInstallInfo> installInfo) {
+        if (mWorkspace != null) {
+            mWorkspace.updatePackageState(installInfo);
+        }
+    }
+
+    /**
+     * Update the label and icon of all the icons in a package
+     *
+     * Implementation of the method from LauncherModel.Callbacks.
+     */
+    @Override
+    public void updatePackageBadge(String packageName) {
+        if (mWorkspace != null) {
+            mWorkspace.updatePackageBadge(packageName, UserHandleCompat.myUserHandle());
+        }
+    }
+
+    /**
      * A package was uninstalled.  We take both the super set of packageNames
      * in addition to specific applications to remove, the reason being that
      * this can be called when a package is updated as well.  In that scenario,
@@ -4155,10 +4771,10 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindComponentsRemoved(final ArrayList<String> packageNames,
-                                      final ArrayList<AppInfo> appInfos) {
+            final ArrayList<AppInfo> appInfos, final UserHandleCompat user) {
         Runnable r = new Runnable() {
             public void run() {
-                bindComponentsRemoved(packageNames, appInfos);
+                bindComponentsRemoved(packageNames, appInfos, user);
             }
         };
         if (waitUntilResume(r)) {
@@ -4166,10 +4782,10 @@
         }
 
         if (!packageNames.isEmpty()) {
-            mWorkspace.removeItemsByPackageName(packageNames);
+            mWorkspace.removeItemsByPackageName(packageNames, user);
         }
         if (!appInfos.isEmpty()) {
-            mWorkspace.removeItemsByApplicationInfo(appInfos);
+            mWorkspace.removeItemsByApplicationInfo(appInfos, user);
         }
 
         // Notify the drag controller
@@ -4267,7 +4883,7 @@
      * @param hint the hint to be displayed in the search bar.
      */
     protected void onSearchBarHintChanged(String hint) {
-        mLauncherClings.updateSearchBarHint(hint);
+
     }
 
     protected boolean isLauncherPreinstalled() {
@@ -4285,6 +4901,17 @@
         }
     }
 
+    /**
+     * This method indicates whether or not we should suggest default wallpaper dimensions
+     * when our wallpaper cropper was not yet used to set a wallpaper.
+     */
+    protected boolean overrideWallpaperDimensions() {
+        return true;
+    }
+
+    protected boolean shouldClingFocusHotseatApp() {
+        return false;
+    }
     protected String getFirstRunClingSearchBarHint() {
         return "";
     }
@@ -4307,38 +4934,41 @@
         return "";
     }
 
-    public void dismissFirstRunCling(View v) {
-        mLauncherClings.dismissFirstRunCling(v);
+    /**
+     * To be overridden by subclasses to indicate that there is an activity to launch
+     * before showing the standard launcher experience.
+     */
+    protected boolean hasFirstRunActivity() {
+        return false;
     }
-    public void dismissMigrationClingCopyApps(View v) {
-        mLauncherClings.dismissMigrationClingCopyApps(v);
-    }
-    public void dismissMigrationClingUseDefault(View v) {
-        mLauncherClings.dismissMigrationClingUseDefault(v);
-    }
-    public void dismissMigrationWorkspaceCling(View v) {
-        mLauncherClings.dismissMigrationWorkspaceCling(v);
-    }
-    public void dismissWorkspaceCling(View v) {
-        mLauncherClings.dismissWorkspaceCling(v);
-    }
-    public void dismissFolderCling(View v) {
-        mLauncherClings.dismissFolderCling(v);
+
+    /**
+     * To be overridden by subclasses to launch any first run activity
+     */
+    protected Intent getFirstRunActivity() {
+        return null;
     }
 
     private boolean shouldRunFirstRunActivity() {
-        return !ActivityManager.isRunningInTestHarness();
+        return !ActivityManager.isRunningInTestHarness() &&
+                !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
     }
 
-    public void showFirstRunActivity() {
-        if (shouldRunFirstRunActivity() && hasFirstRunActivity()
-                && !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false)) {
+    protected boolean hasRunFirstRunActivity() {
+        return mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
+    }
+
+    public boolean showFirstRunActivity() {
+        if (shouldRunFirstRunActivity() &&
+                hasFirstRunActivity()) {
             Intent firstRunIntent = getFirstRunActivity();
             if (firstRunIntent != null) {
                 startActivity(firstRunIntent);
                 markFirstRunActivityShown();
+                return true;
             }
         }
+        return false;
     }
 
     private void markFirstRunActivityShown() {
@@ -4347,38 +4977,129 @@
         editor.apply();
     }
 
+    /**
+     * To be overridden by subclasses to indicate that there is an in-activity full-screen intro
+     * screen that must be displayed and dismissed.
+     */
+    protected boolean hasDismissableIntroScreen() {
+        return false;
+    }
+
+    /**
+     * Full screen intro screen to be shown and dismissed before the launcher can be used.
+     */
+    protected View getIntroScreen() {
+        return null;
+    }
+
+    /**
+     * To be overriden by subclasses to indicate whether the in-activity intro screen has been
+     * dismissed. This method is ignored if #hasDismissableIntroScreen returns false.
+     */
+    private boolean shouldShowIntroScreen() {
+        return hasDismissableIntroScreen() &&
+                !mSharedPrefs.getBoolean(INTRO_SCREEN_DISMISSED, false);
+    }
+
+    protected void showIntroScreen() {
+        View introScreen = getIntroScreen();
+        changeWallpaperVisiblity(false);
+        if (introScreen != null) {
+            mDragLayer.showOverlayView(introScreen);
+        }
+    }
+
+    public void dismissIntroScreen() {
+        markIntroScreenDismissed();
+        if (showFirstRunActivity()) {
+            // We delay hiding the intro view until the first run activity is showing. This
+            // avoids a blip.
+            mWorkspace.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mDragLayer.dismissOverlayView();
+                    showFirstRunClings();
+                }
+            }, ACTIVITY_START_DELAY);
+        } else {
+            mDragLayer.dismissOverlayView();
+            showFirstRunClings();
+        }
+        changeWallpaperVisiblity(true);
+    }
+
+    private void markIntroScreenDismissed() {
+        SharedPreferences.Editor editor = mSharedPrefs.edit();
+        editor.putBoolean(INTRO_SCREEN_DISMISSED, true);
+        editor.apply();
+    }
+
+    private void showFirstRunClings() {
+        // The two first run cling paths are mutually exclusive, if the launcher is preinstalled
+        // on the device, then we always show the first run cling experience (or if there is no
+        // launcher2). Otherwise, we prompt the user upon started for migration
+        LauncherClings launcherClings = new LauncherClings(this);
+        if (launcherClings.shouldShowFirstRunOrMigrationClings()) {
+            if (mModel.canMigrateFromOldLauncherDb(this)) {
+                launcherClings.showMigrationCling();
+            } else {
+                launcherClings.showLongPressCling(true);
+            }
+        }
+    }
+
     void showWorkspaceSearchAndHotseat() {
-        mWorkspace.setAlpha(1f);
-        mHotseat.setAlpha(1f);
-        mPageIndicators.setAlpha(1f);
-        mSearchDropTargetBar.showSearchBar(false);
+        if (mWorkspace != null) mWorkspace.setAlpha(1f);
+        if (mHotseat != null) mHotseat.setAlpha(1f);
+        if (mPageIndicators != null) mPageIndicators.setAlpha(1f);
+        if (mSearchDropTargetBar != null) mSearchDropTargetBar.showSearchBar(false);
     }
 
     void hideWorkspaceSearchAndHotseat() {
-        mWorkspace.setAlpha(0f);
-        mHotseat.setAlpha(0f);
-        mPageIndicators.setAlpha(0f);
-        mSearchDropTargetBar.hideSearchBar(false);
+        if (mWorkspace != null) mWorkspace.setAlpha(0f);
+        if (mHotseat != null) mHotseat.setAlpha(0f);
+        if (mPageIndicators != null) mPageIndicators.setAlpha(0f);
+        if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false);
     }
 
-
     public ItemInfo createAppDragInfo(Intent appLaunchIntent) {
-        ResolveInfo ri = getPackageManager().resolveActivity(appLaunchIntent, 0);
-        if (ri == null) {
+        // Called from search suggestion, not supported in other profiles.
+        final UserHandleCompat myUser = UserHandleCompat.myUserHandle();
+        LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
+        LauncherActivityInfoCompat activityInfo = launcherApps.resolveActivity(appLaunchIntent,
+                myUser);
+        if (activityInfo == null) {
             return null;
         }
-        return new AppInfo(getPackageManager(), ri, mIconCache, null);
+        return new AppInfo(this, activityInfo, myUser, mIconCache, null);
     }
 
     public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
             Bitmap icon) {
-        return new ShortcutInfo(shortcutIntent, caption, icon);
+        // Called from search suggestion, not supported in other profiles.
+        return createShortcutDragInfo(shortcutIntent, caption, icon,
+                UserHandleCompat.myUserHandle());
+    }
+
+    public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
+            Bitmap icon, UserHandleCompat user) {
+        UserManagerCompat userManager = UserManagerCompat.getInstance(this);
+        CharSequence contentDescription = userManager.getBadgedLabelForUser(caption, user);
+        return new ShortcutInfo(shortcutIntent, caption, contentDescription, icon, user);
+    }
+
+    protected void moveWorkspaceToDefaultScreen() {
+        mWorkspace.moveToDefaultScreen(false);
     }
 
     public void startDrag(View dragView, ItemInfo dragInfo, DragSource source) {
         dragView.setTag(dragInfo);
-        mWorkspace.onDragStartedWithItem(dragView);
-        mWorkspace.beginDragShared(dragView, source);
+        mWorkspace.onExternalDragStartedWithItem(dragView);
+        mWorkspace.beginExternalDragShared(dragView, source);
+    }
+
+    @Override
+    public void onPageSwitch(View newPage, int newPageIndex) {
     }
 
     /**
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index e6c220b..be295f8 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -22,6 +22,7 @@
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
 import android.view.View;
+import android.view.ViewAnimationUtils;
 import android.view.ViewTreeObserver;
 
 import java.util.HashSet;
@@ -126,4 +127,14 @@
         new FirstFrameAnimatorHelper(anim, view);
         return anim;
     }
+
+    public static Animator createCircularReveal(View view, int centerX,
+            int centerY, float startRadius, float endRadius) {
+        Animator anim = ViewAnimationUtils.createCircularReveal(view, centerX,
+                centerY, startRadius, endRadius);
+        if (anim instanceof ValueAnimator) {
+            new FirstFrameAnimatorHelper((ValueAnimator) anim, view);
+        }
+        return anim;
+    }
 }
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 5e41fca..246278f 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -17,19 +17,29 @@
 package com.android.launcher3;
 
 import android.app.SearchManager;
-import android.content.*;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.util.Log;
 
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
     private static final String TAG = "LauncherAppState";
     private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
 
+    private static final boolean DEBUG = false;
+
     private final AppFilter mAppFilter;
     private final BuildInfo mBuildInfo;
     private LauncherModel mModel;
@@ -84,22 +94,17 @@
         mIsScreenLarge = isScreenLarge(sContext.getResources());
         mScreenDensity = sContext.getResources().getDisplayMetrics().density;
 
-        mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
+        recreateWidgetPreviewDb();
         mIconCache = new IconCache(sContext);
 
         mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
         mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
         mModel = new LauncherModel(this, mIconCache, mAppFilter);
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
+        launcherApps.addOnAppsChangedCallback(mModel);
 
         // Register intent receivers
-        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        filter.addDataScheme("package");
-        sContext.registerReceiver(mModel, filter);
-        filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         sContext.registerReceiver(mModel, filter);
@@ -116,11 +121,20 @@
                 mFavoritesObserver);
     }
 
+    public void recreateWidgetPreviewDb() {
+        if (mWidgetPreviewCacheDb != null) {
+            mWidgetPreviewCacheDb.close();
+        }
+        mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
+    }
+
     /**
      * Call from Application.onTerminate(), which is not guaranteed to ever be called.
      */
     public void onTerminate() {
         sContext.unregisterReceiver(mModel);
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
+        launcherApps.removeOnAppsChangedCallback(mModel);
 
         ContentResolver resolver = sContext.getContentResolver();
         resolver.unregisterContentObserver(mFavoritesObserver);
@@ -147,7 +161,7 @@
         return mModel;
     }
 
-    IconCache getIconCache() {
+    public IconCache getIconCache() {
         return mIconCache;
     }
 
@@ -238,4 +252,19 @@
         return getInstance().mBuildInfo.isDogfoodBuild() &&
                 Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
     }
+
+    public static boolean isDogfoodBuild() {
+        return getInstance().mBuildInfo.isDogfoodBuild();
+    }
+
+    public void setPackageState(ArrayList<PackageInstallInfo> installInfo) {
+        mModel.setPackageState(installInfo);
+    }
+
+    /**
+     * Updates the icons and label of all icons for the provided package name.
+     */
+    public void updatePackageBadge(String packageName) {
+        mModel.updatePackageBadge(packageName);
+    }
 }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 7b08d44..a309f26 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -20,6 +20,9 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
+import android.os.TransactionTooLargeException;
+
+import java.util.ArrayList;
 
 /**
  * Specific {@link AppWidgetHost} that creates our {@link LauncherAppWidgetHostView}
@@ -28,6 +31,8 @@
  */
 public class LauncherAppWidgetHost extends AppWidgetHost {
 
+    private final ArrayList<Runnable> mProviderChangeListeners = new ArrayList<Runnable>();
+
     Launcher mLauncher;
 
     public LauncherAppWidgetHost(Launcher launcher, int hostId) {
@@ -42,14 +47,42 @@
     }
 
     @Override
+    public void startListening() {
+        try {
+            super.startListening();
+        } catch (Exception e) {
+            if (e.getCause() instanceof TransactionTooLargeException) {
+                // We're willing to let this slide. The exception is being caused by the list of
+                // RemoteViews which is being passed back. The startListening relationship will
+                // have been established by this point, and we will end up populating the
+                // widgets upon bind anyway. See issue 14255011 for more context.
+            } else {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
     public void stopListening() {
         super.stopListening();
         clearViews();
     }
 
+    public void addProviderChangeListener(Runnable callback) {
+        mProviderChangeListeners.add(callback);
+    }
+
+    public void removeProviderChangeListener(Runnable callback) {
+        mProviderChangeListeners.remove(callback);
+    }
+
     protected void onProvidersChanged() {
         // Once we get the message that widget packages are updated, we need to rebind items
         // in AppsCustomize accordingly.
         mLauncher.bindPackagesUpdated(LauncherModel.getSortedWidgetsAndShortcuts(mLauncher));
+
+        for (Runnable callback : mProviderChangeListeners) {
+            callback.run();
+        }
     }
 }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 51a649a..e39727b 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -21,6 +21,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.widget.RemoteViews;
 
@@ -30,12 +31,16 @@
  * {@inheritDoc}
  */
 public class LauncherAppWidgetHostView extends AppWidgetHostView implements TouchCompleteListener {
+
+    LayoutInflater mInflater;
+
     private CheckLongPressHelper mLongPressHelper;
-    private LayoutInflater mInflater;
     private Context mContext;
     private int mPreviousOrientation;
     private DragLayer mDragLayer;
 
+    private float mSlop;
+
     public LauncherAppWidgetHostView(Context context) {
         super(context);
         mContext = context;
@@ -56,7 +61,8 @@
         super.updateAppWidget(remoteViews);
     }
 
-    public boolean orientationChangedSincedInflation() {
+    public boolean isReinflateRequired() {
+        // Re-inflate is required if the orientation has changed since last inflated.
         int orientation = mContext.getResources().getConfiguration().orientation;
         if (mPreviousOrientation != orientation) {
            return true;
@@ -90,6 +96,11 @@
             case MotionEvent.ACTION_CANCEL:
                 mLongPressHelper.cancelLongPress();
                 break;
+            case MotionEvent.ACTION_MOVE:
+                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
+                    mLongPressHelper.cancelLongPress();
+                }
+                break;
         }
 
         // Otherwise continue letting touch events fall through to children
@@ -104,11 +115,22 @@
             case MotionEvent.ACTION_CANCEL:
                 mLongPressHelper.cancelLongPress();
                 break;
+            case MotionEvent.ACTION_MOVE:
+                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
+                    mLongPressHelper.cancelLongPress();
+                }
+                break;
         }
         return false;
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+    }
+
+    @Override
     public void cancelLongPress() {
         super.cancelLongPress();
         mLongPressHelper.cancelLongPress();
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 28df90f..5c6535a 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -19,11 +19,36 @@
 import android.appwidget.AppWidgetHostView;
 import android.content.ComponentName;
 import android.content.ContentValues;
+import android.content.Context;
+
+import com.android.launcher3.compat.UserHandleCompat;
 
 /**
  * Represents a widget (either instantiated or about to be) in the Launcher.
  */
-class LauncherAppWidgetInfo extends ItemInfo {
+public class LauncherAppWidgetInfo extends ItemInfo {
+
+    public static final int RESTORE_COMPLETED = 0;
+
+    /**
+     * This is set during the package backup creation.
+     */
+    public static final int FLAG_ID_NOT_VALID = 1;
+
+    /**
+     * Indicates that the provider is not available yet.
+     */
+    public static final int FLAG_PROVIDER_NOT_READY = 2;
+
+    /**
+     * Indicates that the widget UI is not yet ready, and user needs to set it up again.
+     */
+    public static final int FLAG_UI_NOT_READY = 4;
+
+    /**
+     * Indicates that the widget restore has started.
+     */
+    public static final int FLAG_RESTORE_STARTED = 8;
 
     /**
      * Indicates that the widget hasn't been instantiated yet.
@@ -42,6 +67,16 @@
     int minWidth = -1;
     int minHeight = -1;
 
+    /**
+     * Indicates the restore status of the widget.
+     */
+    int restoreStatus;
+
+    /**
+     * Indicates the installation progress of the widget provider
+     */
+    int installProgress = -1;
+
     private boolean mHasNotifiedInitialWidgetSizeChanged;
 
     /**
@@ -59,13 +94,17 @@
         // to indicate that they should be calculated based on the layout and minWidth/minHeight
         spanX = -1;
         spanY = -1;
+        // We only support app widgets on current user.
+        user = UserHandleCompat.myUserHandle();
+        restoreStatus = RESTORE_COMPLETED;
     }
 
     @Override
-    void onAddToDatabase(ContentValues values) {
-        super.onAddToDatabase(values);
+    void onAddToDatabase(Context context, ContentValues values) {
+        super.onAddToDatabase(context, values);
         values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString());
+        values.put(LauncherSettings.Favorites.RESTORED, restoreStatus);
     }
 
     /**
@@ -96,4 +135,12 @@
         super.unbind();
         hostView = null;
     }
+
+    public final boolean isWidgetIdValid() {
+        return (restoreStatus & FLAG_ID_NOT_VALID) == 0;
+    }
+
+    public final boolean hasRestoreFlag(int flag) {
+        return (restoreStatus & flag) == flag;
+    }
 }
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 83e4a60..c20c693 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -17,17 +17,26 @@
 package com.android.launcher3;
 
 import android.app.backup.BackupAgentHelper;
+import android.app.backup.BackupDataInput;
 import android.app.backup.BackupManager;
-import android.app.backup.SharedPreferencesBackupHelper;
 import android.content.Context;
-import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.io.IOException;
 
 public class LauncherBackupAgentHelper extends BackupAgentHelper {
 
     private static final String TAG = "LauncherBackupAgentHelper";
+    static final boolean VERBOSE = true;
+    static final boolean DEBUG = false;
 
     private static BackupManager sBackupManager;
 
+    protected static final String SETTING_RESTORE_ENABLED = "launcher_restore_enabled";
+
     /**
      * Notify the backup manager that out database is dirty.
      *
@@ -48,15 +57,38 @@
         // modifies the file outside the normal codepaths, so it looks like another
         // process.  This forces a reload of the file, in case this process persists.
         String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+        getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
         super.onDestroy();
     }
 
     @Override
     public void onCreate() {
+        boolean restoreEnabled = 0 != Settings.Secure.getInt(
+                getContentResolver(), SETTING_RESTORE_ENABLED, 1);
+        if (VERBOSE) Log.v(TAG, "restore is " + (restoreEnabled ? "enabled" : "disabled"));
+
         addHelper(LauncherBackupHelper.LAUNCHER_PREFS_PREFIX,
-                new SharedPreferencesBackupHelper(this,
-                        LauncherAppState.getSharedPreferencesKey()));
-        addHelper(LauncherBackupHelper.LAUNCHER_PREFIX, new LauncherBackupHelper(this));
+                new LauncherPreferencesBackupHelper(this,
+                        LauncherAppState.getSharedPreferencesKey(),
+                        restoreEnabled));
+        addHelper(LauncherBackupHelper.LAUNCHER_PREFIX,
+                new LauncherBackupHelper(this, restoreEnabled));
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        super.onRestore(data, appVersionCode, newState);
+
+        // If no favorite was migrated, clear the data and start fresh.
+        final Cursor c = getContentResolver().query(
+                LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, null, null, null, null);
+        boolean hasData = c.moveToNext();
+        c.close();
+
+        if (!hasData) {
+            if (VERBOSE) Log.v(TAG, "Nothing was restored, clearing DB");
+            LauncherAppState.getLauncherProvider().createEmptyDB();
+        }
     }
 }
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 68bef00..201f3e9 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.android.launcher3;
 
 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
@@ -29,6 +28,8 @@
 import com.android.launcher3.backup.BackupProtos.Resource;
 import com.android.launcher3.backup.BackupProtos.Screen;
 import com.android.launcher3.backup.BackupProtos.Widget;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.compat.UserHandleCompat;
 
 import android.app.backup.BackupDataInputStream;
 import android.app.backup.BackupDataOutput;
@@ -38,6 +39,7 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
@@ -67,7 +69,8 @@
 public class LauncherBackupHelper implements BackupHelper {
 
     private static final String TAG = "LauncherBackupHelper";
-    private static final boolean DEBUG = false;
+    private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
+    private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;
     private static final boolean DEBUG_PAYLOAD = false;
 
     private static final int MAX_JOURNAL_SIZE = 1000000;
@@ -107,6 +110,7 @@
             Favorites.SPANX,                   // 14
             Favorites.SPANY,                   // 15
             Favorites.TITLE,                   // 16
+            Favorites.PROFILE_ID,              // 17
     };
 
     private static final int ID_INDEX = 0;
@@ -126,6 +130,7 @@
     private static final int SPANX_INDEX = 14;
     private static final int SPANY_INDEX = 15;
     private static final int TITLE_INDEX = 16;
+    private static final int PROFILE_ID_INDEX = 17;
 
     private static final String[] SCREEN_PROJECTION = {
             WorkspaceScreens._ID,              // 0
@@ -135,14 +140,20 @@
 
     private static final int SCREEN_RANK_INDEX = 2;
 
+    private static IconCache mIconCache;
+
     private final Context mContext;
 
+    private final boolean mRestoreEnabled;
+
     private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap;
 
-    private ArrayList<Key> mKeys;
+    private final ArrayList<Key> mKeys;
 
-    public LauncherBackupHelper(Context context) {
+    public LauncherBackupHelper(Context context, boolean restoreEnabled) {
         mContext = context;
+        mRestoreEnabled = restoreEnabled;
+        mKeys = new ArrayList<Key>();
     }
 
     private void dataChanged() {
@@ -167,7 +178,7 @@
     @Override
     public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState) {
-        Log.v(TAG, "onBackup");
+        if (VERBOSE) Log.v(TAG, "onBackup");
 
         Journal in = readJournal(oldState);
         Journal out = new Journal();
@@ -177,19 +188,23 @@
         out.rows = 0;
         out.bytes = 0;
 
-        Log.v(TAG, "lastBackupTime=" + lastBackupTime);
+        Log.v(TAG, "lastBackupTime = " + lastBackupTime);
 
         ArrayList<Key> keys = new ArrayList<Key>();
-        try {
-            backupFavorites(in, data, out, keys);
-            backupScreens(in, data, out, keys);
-            backupIcons(in, data, out, keys);
-            backupWidgets(in, data, out, keys);
-        } catch (IOException e) {
-            Log.e(TAG, "launcher backup has failed", e);
+        if (launcherIsReady()) {
+            try {
+                backupFavorites(in, data, out, keys);
+                backupScreens(in, data, out, keys);
+                backupIcons(in, data, out, keys);
+                backupWidgets(in, data, out, keys);
+            } catch (IOException e) {
+                Log.e(TAG, "launcher backup has failed", e);
+            }
+            out.key = keys.toArray(new BackupProtos.Key[keys.size()]);
+        } else {
+            out = in;
         }
 
-        out.key = keys.toArray(BackupProtos.Key.emptyArray());
         writeJournal(newState, out);
         Log.v(TAG, "onBackup: wrote " + out.bytes + "b in " + out.rows + " rows.");
     }
@@ -203,10 +218,7 @@
      */
     @Override
     public void restoreEntity(BackupDataInputStream data) {
-        Log.v(TAG, "restoreEntity");
-        if (mKeys == null) {
-            mKeys = new ArrayList<Key>();
-        }
+        if (VERBOSE) Log.v(TAG, "restoreEntity");
         byte[] buffer = new byte[512];
             String backupKey = data.getKey();
             int dataSize = data.size();
@@ -219,10 +231,11 @@
             bytesRead = data.read(buffer, 0, dataSize);
             if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available");
         } catch (IOException e) {
-            Log.d(TAG, "failed to read entity from restore data", e);
+            Log.e(TAG, "failed to read entity from restore data", e);
         }
         try {
             key = backupKeyToKey(backupKey);
+            mKeys.add(key);
             switch (key.type) {
                 case Key.FAVORITE:
                     restoreFavorite(key, buffer, dataSize, mKeys);
@@ -261,7 +274,7 @@
         // will catch any changes the restore process might have made
         Journal out = new Journal();
         out.t = 0;
-        out.key = mKeys.toArray(BackupProtos.Key.emptyArray());
+        out.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
         writeJournal(newState, out);
         Log.v(TAG, "onRestore: read " + mKeys.size() + " rows");
         mKeys.clear();
@@ -286,8 +299,9 @@
 
         // persist things that have changed since the last backup
         ContentResolver cr = mContext.getContentResolver();
+        // Don't backup apps in other profiles for now.
         Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
-                null, null, null);
+                getUserSelectionArg(), null, null);
         Set<String> currentIds = new HashSet<String>(cursor.getCount());
         try {
             cursor.moveToPosition(-1);
@@ -296,10 +310,13 @@
                 final long updateTime = cursor.getLong(ID_MODIFIED);
                 Key key = getKey(Key.FAVORITE, id);
                 keys.add(key);
-                currentIds.add(keyToBackupKey(key));
-                if (updateTime >= in.t) {
+                final String backupKey = keyToBackupKey(key);
+                currentIds.add(backupKey);
+                if (!savedIds.contains(backupKey) || updateTime >= in.t) {
                     byte[] blob = packFavorite(cursor);
                     writeRowToBackup(key, blob, out, data);
+                } else {
+                    if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
                 }
             }
         } finally {
@@ -323,15 +340,21 @@
      * @param keys keys to mark as clean in the notes for next backup
      */
     private void restoreFavorite(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
-        Log.v(TAG, "unpacking favorite " + key.id + " (" + dataSize + " bytes)");
+        if (VERBOSE) Log.v(TAG, "unpacking favorite " + key.id);
         if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
                 Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
 
+        if (!mRestoreEnabled) {
+            if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+            return;
+        }
+
         try {
-            Favorite favorite =  unpackFavorite(buffer, 0, dataSize);
-            if (DEBUG) Log.d(TAG, "unpacked " + favorite.itemType);
+            ContentResolver cr = mContext.getContentResolver();
+            ContentValues values = unpackFavorite(buffer, 0, dataSize);
+            cr.insert(Favorites.CONTENT_URI_NO_NOTIFICATION, values);
         } catch (InvalidProtocolBufferNanoException e) {
-            Log.w(TAG, "failed to decode proto", e);
+            Log.e(TAG, "failed to decode favorite", e);
         }
     }
 
@@ -359,15 +382,19 @@
         Set<String> currentIds = new HashSet<String>(cursor.getCount());
         try {
             cursor.moveToPosition(-1);
+            if (DEBUG) Log.d(TAG, "dumping screens after: " + in.t);
             while(cursor.moveToNext()) {
                 final long id = cursor.getLong(ID_INDEX);
                 final long updateTime = cursor.getLong(ID_MODIFIED);
                 Key key = getKey(Key.SCREEN, id);
                 keys.add(key);
-                currentIds.add(keyToBackupKey(key));
-                if (updateTime >= in.t) {
+                final String backupKey = keyToBackupKey(key);
+                currentIds.add(backupKey);
+                if (!savedIds.contains(backupKey) || updateTime >= in.t) {
                     byte[] blob = packScreen(cursor);
                     writeRowToBackup(key, blob, out, data);
+                } else {
+                    if (VERBOSE) Log.v(TAG, "screen " + id + " was too old: " + updateTime);
                 }
             }
         } finally {
@@ -391,14 +418,22 @@
      * @param keys keys to mark as clean in the notes for next backup
      */
     private void restoreScreen(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
-        Log.v(TAG, "unpacking screen " + key.id);
+        if (VERBOSE) Log.v(TAG, "unpacking screen " + key.id);
         if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
                 Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
+
+        if (!mRestoreEnabled) {
+            if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+            return;
+        }
+
         try {
-            Screen screen = unpackScreen(buffer, 0, dataSize);
-            if (DEBUG) Log.d(TAG, "unpacked " + screen.rank);
+            ContentResolver cr = mContext.getContentResolver();
+            ContentValues values = unpackScreen(buffer, 0, dataSize);
+            cr.insert(WorkspaceScreens.CONTENT_URI, values);
+
         } catch (InvalidProtocolBufferNanoException e) {
-            Log.w(TAG, "failed to decode proto", e);
+            Log.e(TAG, "failed to decode screen", e);
         }
     }
 
@@ -415,23 +450,26 @@
     private void backupIcons(Journal in, BackupDataOutput data, Journal out,
             ArrayList<Key> keys) throws IOException {
         // persist icons that haven't been persisted yet
-        final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
-        if (appState == null) {
+        if (!initializeIconCache()) {
             dataChanged(); // try again later
             if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying icon backup");
             return;
         }
         final ContentResolver cr = mContext.getContentResolver();
-        final IconCache iconCache = appState.getIconCache();
         final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
+        final UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
 
         // read the old ID set
         Set<String> savedIds = getSavedIdsByType(Key.ICON, in);
         if (DEBUG) Log.d(TAG, "icon savedIds.size()=" + savedIds.size());
 
+        // Don't backup apps in other profiles for now.
         int startRows = out.rows;
         if (DEBUG) Log.d(TAG, "starting here: " + startRows);
-        String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPLICATION;
+
+        String where = "(" + Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPLICATION + " OR " +
+                Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_SHORTCUT + ") AND " +
+                getUserSelectionArg();
         Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
                 where, null, null);
         Set<String> currentIds = new HashSet<String>(cursor.getCount());
@@ -453,30 +491,30 @@
                         Log.w(TAG, "empty intent on application favorite: " + id);
                     }
                     if (savedIds.contains(backupKey)) {
-                        if (DEBUG) Log.d(TAG, "already saved icon " + backupKey);
+                        if (VERBOSE) Log.v(TAG, "already saved icon " + backupKey);
 
                         // remember that we already backed this up previously
                         keys.add(key);
                     } else if (backupKey != null) {
                         if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
                         if ((out.rows - startRows) < MAX_ICONS_PER_PASS) {
-                            if (DEBUG) Log.d(TAG, "saving icon " + backupKey);
-                            Bitmap icon = iconCache.getIcon(intent);
+                            if (VERBOSE) Log.v(TAG, "saving icon " + backupKey);
+                            Bitmap icon = mIconCache.getIcon(intent, myUserHandle);
                             keys.add(key);
-                            if (icon != null && !iconCache.isDefaultIcon(icon)) {
+                            if (icon != null && !mIconCache.isDefaultIcon(icon, myUserHandle)) {
                                 byte[] blob = packIcon(dpi, icon);
                                 writeRowToBackup(key, blob, out, data);
                             }
                         } else {
-                            if (DEBUG) Log.d(TAG, "scheduling another run for icon " + backupKey);
+                            if (VERBOSE) Log.d(TAG, "deferring icon backup " + backupKey);
                             // too many icons for this pass, request another.
                             dataChanged();
                         }
                     }
                 } catch (URISyntaxException e) {
-                    Log.w(TAG, "invalid URI on application favorite: " + id);
+                    Log.e(TAG, "invalid URI on application favorite: " + id);
                 } catch (IOException e) {
-                    Log.w(TAG, "unable to save application icon for favorite: " + id);
+                    Log.e(TAG, "unable to save application icon for favorite: " + id);
                 }
 
             }
@@ -501,21 +539,37 @@
      * @param keys keys to mark as clean in the notes for next backup
      */
     private void restoreIcon(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
-        Log.v(TAG, "unpacking icon " + key.id);
+        if (VERBOSE) Log.v(TAG, "unpacking icon " + key.id);
         if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
                 Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
+
         try {
             Resource res = unpackIcon(buffer, 0, dataSize);
-            if (DEBUG) Log.d(TAG, "unpacked " + res.dpi);
-            if (DEBUG) Log.d(TAG, "read " +
-                    Base64.encodeToString(res.data, 0, res.data.length,
-                            Base64.NO_WRAP));
+            if (DEBUG) {
+                Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
+            }
+            if (DEBUG_PAYLOAD) {
+                Log.d(TAG, "read " +
+                        Base64.encodeToString(res.data, 0, res.data.length,
+                                Base64.NO_WRAP));
+            }
             Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
             if (icon == null) {
                 Log.w(TAG, "failed to unpack icon for " + key.name);
             }
-        } catch (InvalidProtocolBufferNanoException e) {
-            Log.w(TAG, "failed to decode proto", e);
+
+            if (!mRestoreEnabled) {
+                if (VERBOSE) {
+                    Log.v(TAG, "restore not enabled: skipping database mutation");
+                }
+                return;
+            } else {
+                if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
+                IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name),
+                        icon, res.dpi);
+            }
+        } catch (IOException e) {
+            Log.d(TAG, "failed to save restored icon for: " + key.name, e);
         }
     }
 
@@ -533,15 +587,13 @@
             ArrayList<Key> keys) throws IOException {
         // persist static widget info that hasn't been persisted yet
         final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
-        if (appState == null) {
-            dataChanged(); // try again later
-            if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying widget backup");
+        if (appState == null || !initializeIconCache()) {
+            Log.w(TAG, "Failed to get icon cache during restore");
             return;
         }
         final ContentResolver cr = mContext.getContentResolver();
         final WidgetPreviewLoader previewLoader = new WidgetPreviewLoader(mContext);
         final PagedViewCellLayout widgetSpacingLayout = new PagedViewCellLayout(mContext);
-        final IconCache iconCache = appState.getIconCache();
         final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
         final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile();
         if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx);
@@ -552,7 +604,8 @@
 
         int startRows = out.rows;
         if (DEBUG) Log.d(TAG, "starting here: " + startRows);
-        String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET;
+        String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET + " AND "
+                + getUserSelectionArg();
         Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
                 where, null, null);
         Set<String> currentIds = new HashSet<String>(cursor.getCount());
@@ -574,22 +627,22 @@
                     Log.w(TAG, "empty intent on appwidget: " + id);
                 }
                 if (savedIds.contains(backupKey)) {
-                    if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
+                    if (VERBOSE) Log.v(TAG, "already saved widget " + backupKey);
 
                     // remember that we already backed this up previously
                     keys.add(key);
                 } else if (backupKey != null) {
                     if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
                     if ((out.rows - startRows) < MAX_WIDGETS_PER_PASS) {
-                        if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
+                        if (VERBOSE) Log.v(TAG, "saving widget " + backupKey);
                         previewLoader.setPreviewSize(spanX * profile.cellWidthPx,
                                 spanY * profile.cellHeightPx, widgetSpacingLayout);
-                        byte[] blob = packWidget(dpi, previewLoader, iconCache, provider);
+                        byte[] blob = packWidget(dpi, previewLoader, mIconCache, provider);
                         keys.add(key);
                         writeRowToBackup(key, blob, out, data);
 
                     } else {
-                        if (DEBUG) Log.d(TAG, "scheduling another run for widget " + backupKey);
+                        if (VERBOSE) Log.d(TAG, "deferring widget backup " + backupKey);
                         // too many widgets for this pass, request another.
                         dataChanged();
                     }
@@ -616,7 +669,7 @@
      * @param keys keys to mark as clean in the notes for next backup
      */
     private void restoreWidget(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
-        Log.v(TAG, "unpacking widget " + key.id);
+        if (VERBOSE) Log.v(TAG, "unpacking widget " + key.id);
         if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
                 Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
         try {
@@ -627,10 +680,20 @@
                         .decodeByteArray(widget.icon.data, 0, widget.icon.data.length);
                 if (icon == null) {
                     Log.w(TAG, "failed to unpack widget icon for " + key.name);
+                } else {
+                    IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(widget.provider),
+                            icon, widget.icon.dpi);
                 }
             }
+
+            if (!mRestoreEnabled) {
+                if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+                return;
+            } else {
+                // future site of widget table mutation
+            }
         } catch (InvalidProtocolBufferNanoException e) {
-            Log.w(TAG, "failed to decode proto", e);
+            Log.e(TAG, "failed to decode widget", e);
         }
     }
 
@@ -748,9 +811,15 @@
         if (!TextUtils.isEmpty(title)) {
             favorite.title = title;
         }
-        String intent = c.getString(INTENT_INDEX);
-        if (!TextUtils.isEmpty(intent)) {
-            favorite.intent = intent;
+        String intentDescription = c.getString(INTENT_INDEX);
+        if (!TextUtils.isEmpty(intentDescription)) {
+            try {
+                Intent intent = Intent.parseUri(intentDescription, 0);
+                intent.removeExtra(ItemInfo.EXTRA_PROFILE);
+                favorite.intent = intent.toUri(0);
+            } catch (URISyntaxException e) {
+                Log.e(TAG, "Invalid intent", e);
+           }
         }
         favorite.itemType = c.getInt(ITEM_TYPE_INDEX);
         if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
@@ -765,11 +834,58 @@
     }
 
     /** Deserialize a Favorite from persistence, after verifying checksum wrapper. */
-    private Favorite unpackFavorite(byte[] buffer, int offset, int dataSize)
+    private ContentValues unpackFavorite(byte[] buffer, int offset, int dataSize)
             throws InvalidProtocolBufferNanoException {
         Favorite favorite = new Favorite();
         MessageNano.mergeFrom(favorite, readCheckedBytes(buffer, offset, dataSize));
-        return favorite;
+        if (VERBOSE) Log.v(TAG, "unpacked favorite " + favorite.itemType + ", " +
+                (TextUtils.isEmpty(favorite.title) ? favorite.id : favorite.title));
+        ContentValues values = new ContentValues();
+        values.put(Favorites._ID, favorite.id);
+        values.put(Favorites.SCREEN, favorite.screen);
+        values.put(Favorites.CONTAINER, favorite.container);
+        values.put(Favorites.CELLX, favorite.cellX);
+        values.put(Favorites.CELLY, favorite.cellY);
+        values.put(Favorites.SPANX, favorite.spanX);
+        values.put(Favorites.SPANY, favorite.spanY);
+        values.put(Favorites.ICON_TYPE, favorite.iconType);
+        if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
+            values.put(Favorites.ICON_PACKAGE, favorite.iconPackage);
+            values.put(Favorites.ICON_RESOURCE, favorite.iconResource);
+        }
+        if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
+            values.put(Favorites.ICON, favorite.icon);
+        }
+        if (!TextUtils.isEmpty(favorite.title)) {
+            values.put(Favorites.TITLE, favorite.title);
+        } else {
+            values.put(Favorites.TITLE, "");
+        }
+        if (!TextUtils.isEmpty(favorite.intent)) {
+            values.put(Favorites.INTENT, favorite.intent);
+        }
+        values.put(Favorites.ITEM_TYPE, favorite.itemType);
+
+        UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
+        long userSerialNumber =
+                UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle);
+        values.put(LauncherSettings.Favorites.PROFILE_ID, userSerialNumber);
+
+        if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+            if (!TextUtils.isEmpty(favorite.appWidgetProvider)) {
+                values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider);
+            }
+            values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId);
+            values.put(LauncherSettings.Favorites.RESTORED,
+                    LauncherAppWidgetInfo.FLAG_ID_NOT_VALID |
+                    LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY |
+                    LauncherAppWidgetInfo.FLAG_UI_NOT_READY);
+        } else {
+            // Let LauncherModel know we've been here.
+            values.put(LauncherSettings.Favorites.RESTORED, 1);
+        }
+
+        return values;
     }
 
     /** Serialize a Screen for persistence, including a checksum wrapper. */
@@ -782,11 +898,15 @@
     }
 
     /** Deserialize a Screen from persistence, after verifying checksum wrapper. */
-    private Screen unpackScreen(byte[] buffer, int offset, int dataSize)
+    private ContentValues unpackScreen(byte[] buffer, int offset, int dataSize)
             throws InvalidProtocolBufferNanoException {
         Screen screen = new Screen();
         MessageNano.mergeFrom(screen, readCheckedBytes(buffer, offset, dataSize));
-        return screen;
+        if (VERBOSE) Log.v(TAG, "unpacked screen " + screen.id + "/" + screen.rank);
+        ContentValues values = new ContentValues();
+        values.put(WorkspaceScreens._ID, screen.id);
+        values.put(WorkspaceScreens.SCREEN_RANK, screen.rank);
+        return values;
     }
 
     /** Serialize an icon Resource for persistence, including a checksum wrapper. */
@@ -801,10 +921,11 @@
     }
 
     /** Deserialize an icon resource from persistence, after verifying checksum wrapper. */
-    private Resource unpackIcon(byte[] buffer, int offset, int dataSize)
+    private static Resource unpackIcon(byte[] buffer, int offset, int dataSize)
             throws InvalidProtocolBufferNanoException {
         Resource res = new Resource();
         MessageNano.mergeFrom(res, readCheckedBytes(buffer, offset, dataSize));
+        if (VERBOSE) Log.v(TAG, "unpacked icon " + res.dpi + "/" + res.data.length);
         return res;
     }
 
@@ -843,6 +964,7 @@
             throws InvalidProtocolBufferNanoException {
         Widget widget = new Widget();
         MessageNano.mergeFrom(widget, readCheckedBytes(buffer, offset, dataSize));
+        if (VERBOSE) Log.v(TAG, "unpacked widget " + widget.provider);
         return widget;
     }
 
@@ -853,7 +975,7 @@
      * in that case, do a full backup.
      *
      * @param oldState the read-0only file descriptor pointing to the old journal
-     * @return a Journal protocol bugffer
+     * @return a Journal protocol buffer
      */
     private Journal readJournal(ParcelFileDescriptor oldState) {
         Journal journal = new Journal();
@@ -862,47 +984,61 @@
         }
         FileInputStream inStream = new FileInputStream(oldState.getFileDescriptor());
         try {
-            int remaining = inStream.available();
-            if (DEBUG) Log.d(TAG, "available " + remaining);
-            if (remaining < MAX_JOURNAL_SIZE) {
-                byte[] buffer = new byte[remaining];
+            int availableBytes = inStream.available();
+            if (DEBUG) Log.d(TAG, "available " + availableBytes);
+            if (availableBytes < MAX_JOURNAL_SIZE) {
+                byte[] buffer = new byte[availableBytes];
                 int bytesRead = 0;
-                while (remaining > 0) {
+                boolean valid = false;
+                InvalidProtocolBufferNanoException lastProtoException = null;
+                while (availableBytes > 0) {
                     try {
-                        int result = inStream.read(buffer, bytesRead, remaining);
+                        // OMG what are you doing? This is crazy inefficient!
+                        // If we read a byte that is not ours, we will cause trouble: b/12491813
+                        // However, we don't know how many bytes to expect (oops).
+                        // So we have to step through *slowly*, watching for the end.
+                        int result = inStream.read(buffer, bytesRead, 1);
                         if (result > 0) {
-                            if (DEBUG) Log.d(TAG, "read some bytes: " + result);
-                            remaining -= result;
+                            availableBytes -= result;
                             bytesRead += result;
+                            if (DEBUG && (bytesRead % 100 == 0)) {
+                                Log.d(TAG, "read some bytes: " + bytesRead);
+                            }
                         } else {
-                            // stop reading ands see what there is to parse
-                            Log.w(TAG, "read error: " + result);
-                            remaining = 0;
+                            Log.w(TAG, "unexpected end of file while reading journal.");
+                            // stop reading and see what there is to parse
+                            availableBytes = 0;
                         }
                     } catch (IOException e) {
-                        Log.w(TAG, "failed to read the journal", e);
                         buffer = null;
-                        remaining = 0;
+                        availableBytes = 0;
                     }
-                }
-                if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead);
 
-                if (buffer != null) {
+                    // check the buffer to see if we have a valid journal
                     try {
                         MessageNano.mergeFrom(journal, readCheckedBytes(buffer, 0, bytesRead));
+                        // if we are here, then we have read a valid, checksum-verified journal
+                        valid = true;
+                        availableBytes = 0;
+                        if (VERBOSE) Log.v(TAG, "read " + bytesRead + " bytes of journal");
                     } catch (InvalidProtocolBufferNanoException e) {
-                        Log.d(TAG, "failed to read the journal", e);
+                        // if we don't have the whole journal yet, mergeFrom will throw. keep going.
+                        lastProtoException = e;
                         journal.clear();
                     }
                 }
+                if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead);
+                if (!valid) {
+                    Log.w(TAG, "could not find a valid journal", lastProtoException);
+                }
             }
         } catch (IOException e) {
-            Log.d(TAG, "failed to close the journal", e);
+            Log.w(TAG, "failed to close the journal", e);
         } finally {
             try {
                 inStream.close();
             } catch (IOException e) {
-                Log.d(TAG, "failed to close the journal", e);
+                Log.w(TAG, "failed to close the journal", e);
             }
         }
         return journal;
@@ -915,7 +1051,7 @@
         data.writeEntityData(blob, blob.length);
         out.rows++;
         out.bytes += blob.length;
-        Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
+        if (VERBOSE) Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
                 getKeyName(key) + "/" + blob.length);
         if(DEBUG_PAYLOAD) {
             String encoded = Base64.encodeToString(blob, 0, blob.length, Base64.NO_WRAP);
@@ -923,7 +1059,7 @@
             for (int offset = 0; offset < encoded.length(); offset += chunkSize) {
                 int end = offset + chunkSize;
                 end = Math.min(end, encoded.length());
-                Log.d(TAG, "wrote " + encoded.substring(offset, end));
+                Log.w(TAG, "wrote " + encoded.substring(offset, end));
             }
         }
     }
@@ -943,7 +1079,7 @@
             throws IOException {
         int rows = 0;
         for(String deleted: deletedIds) {
-            Log.v(TAG, "dropping icon " + deleted);
+            if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
             data.writeEntityHeader(deleted, -1);
             rows++;
         }
@@ -963,10 +1099,12 @@
         FileOutputStream outStream = null;
         try {
             outStream = new FileOutputStream(newState.getFileDescriptor());
-            outStream.write(writeCheckedBytes(journal));
+            final byte[] journalBytes = writeCheckedBytes(journal);
+            outStream.write(journalBytes);
             outStream.close();
+            if (VERBOSE) Log.v(TAG, "wrote " + journalBytes.length + " bytes of journal");
         } catch (IOException e) {
-            Log.d(TAG, "failed to write backup journal", e);
+            Log.w(TAG, "failed to write backup journal", e);
         }
     }
 
@@ -981,7 +1119,7 @@
     }
 
     /** Unwrap a proto message from a CheckedMessage, verifying the checksum. */
-    private byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
+    private static byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
             throws InvalidProtocolBufferNanoException {
         CheckedMessage wrapper = new CheckedMessage();
         MessageNano.mergeFrom(wrapper, buffer, offset, dataSize);
@@ -1005,6 +1143,48 @@
         return mWidgetMap.get(component);
     }
 
+
+    private boolean initializeIconCache() {
+        if (mIconCache != null) {
+            return true;
+        }
+
+        final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+        if (appState == null) {
+            Throwable stackTrace = new Throwable();
+            stackTrace.fillInStackTrace();
+            Log.w(TAG, "Failed to get app state during backup/restore", stackTrace);
+            return false;
+        }
+        mIconCache = appState.getIconCache();
+        return mIconCache != null;
+    }
+
+
+   // check if the launcher is in a state to support backup
+    private boolean launcherIsReady() {
+        ContentResolver cr = mContext.getContentResolver();
+        Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, null, null, null);
+        if (cursor == null) {
+            // launcher data has been wiped, do nothing
+            return false;
+        }
+        cursor.close();
+
+        if (!initializeIconCache()) {
+            // launcher services are unavailable, try again later
+            dataChanged();
+            return false;
+        }
+
+        return true;
+    }
+
+    private String getUserSelectionArg() {
+        return Favorites.PROFILE_ID + '=' + UserManagerCompat.getInstance(mContext)
+                .getSerialNumberForUser(UserHandleCompat.myUserHandle());
+    }
+
     private class KeyParsingException extends Throwable {
         private KeyParsingException(Throwable cause) {
             super(cause);
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
index 45f068b..458d81f 100644
--- a/src/com/android/launcher3/LauncherClings.java
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -18,79 +18,205 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserManager;
+import android.provider.Settings;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityManager;
-import android.widget.TextView;
 
-class LauncherClings {
-    private static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
+class LauncherClings implements OnClickListener {
     private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
-    private static final String MIGRATION_WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
     private static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
-    private static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
+
+    private static final String TAG_CROP_TOP_AND_SIDES = "crop_bg_top_and_sides";
 
     private static final boolean DISABLE_CLINGS = false;
-    private static final boolean DISABLE_CUSTOM_CLINGS = true;
 
     private static final int SHOW_CLING_DURATION = 250;
     private static final int DISMISS_CLING_DURATION = 200;
 
+    // New Secure Setting in L
+    private static final String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
+
     private Launcher mLauncher;
     private LayoutInflater mInflater;
-    private HideFromAccessibilityHelper mHideFromAccessibilityHelper
-            = new HideFromAccessibilityHelper();
 
     /** Ctor */
     public LauncherClings(Launcher launcher) {
         mLauncher = launcher;
-        mInflater = mLauncher.getLayoutInflater();
+        mInflater = LayoutInflater.from(new
+                ContextThemeWrapper(mLauncher, android.R.style.Theme_DeviceDefault));
     }
 
-    /** Initializes a cling */
-    private Cling initCling(int clingId, int scrimId, boolean animate,
-                            boolean dimNavBarVisibilty) {
-        Cling cling = (Cling) mLauncher.findViewById(clingId);
-        View scrim = null;
-        if (scrimId > 0) {
-            scrim = mLauncher.findViewById(R.id.cling_scrim);
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.cling_dismiss_migration_use_default) {
+            // Disable the migration cling
+            dismissMigrationCling();
+        } else if (id == R.id.cling_dismiss_migration_copy_apps) {
+            // Copy the shortcuts from the old database
+            LauncherModel model = mLauncher.getModel();
+            model.resetLoadedState(false, true);
+            model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+                    LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
+                            | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
+            // Set the flag to skip the folder cling
+            String spKey = LauncherAppState.getSharedPreferencesKey();
+            SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+            SharedPreferences.Editor editor = sp.edit();
+            editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
+            editor.apply();
+            // Disable the migration cling
+            dismissMigrationCling();
+        } else if (id == R.id.cling_dismiss_longpress_info) {
+            dismissLongPressCling();
         }
-        if (cling != null) {
-            cling.init(mLauncher, scrim);
-            cling.show(animate, SHOW_CLING_DURATION);
+    }
 
-            if (dimNavBarVisibilty) {
-                cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
-                        View.SYSTEM_UI_FLAG_LOW_PROFILE);
+    /**
+     * Shows the migration cling.
+     *
+     * This flow is mutually exclusive with showFirstRunCling, and only runs if this Launcher
+     * package was not preinstalled and there exists a db to migrate from.
+     */
+    public void showMigrationCling() {
+        mLauncher.hideWorkspaceSearchAndHotseat();
+
+        ViewGroup root = (ViewGroup) mLauncher.findViewById(R.id.launcher);
+        View inflated = mInflater.inflate(R.layout.migration_cling, root);
+        inflated.findViewById(R.id.cling_dismiss_migration_copy_apps).setOnClickListener(this);
+        inflated.findViewById(R.id.cling_dismiss_migration_use_default).setOnClickListener(this);
+    }
+
+    private void dismissMigrationCling() {
+        mLauncher.showWorkspaceSearchAndHotseat();
+        Runnable dismissCb = new Runnable() {
+            public void run() {
+                Runnable cb = new Runnable() {
+                    public void run() {
+                        // Show the longpress cling next
+                        showLongPressCling(false);
+                    }
+                };
+                dismissCling(mLauncher.findViewById(R.id.migration_cling), cb,
+                        MIGRATION_CLING_DISMISSED_KEY, DISMISS_CLING_DURATION);
+            }
+        };
+        mLauncher.getWorkspace().post(dismissCb);
+    }
+
+    public void showLongPressCling(boolean showWelcome) {
+        ViewGroup root = (ViewGroup) mLauncher.findViewById(R.id.launcher);
+        View cling = mInflater.inflate(R.layout.longpress_cling, root, false);
+
+        cling.setOnLongClickListener(new OnLongClickListener() {
+
+            @Override
+            public boolean onLongClick(View v) {
+                mLauncher.getWorkspace().enterOverviewMode();
+                dismissLongPressCling();
+                return true;
+            }
+        });
+
+        final ViewGroup content = (ViewGroup) cling.findViewById(R.id.cling_content);
+        mInflater.inflate(showWelcome ? R.layout.longpress_cling_welcome_content
+                : R.layout.longpress_cling_content, content);
+        content.findViewById(R.id.cling_dismiss_longpress_info).setOnClickListener(this);
+
+        if (TAG_CROP_TOP_AND_SIDES.equals(content.getTag())) {
+            Drawable bg = new BorderCropDrawable(mLauncher.getResources().getDrawable(R.drawable.cling_bg),
+                    true, true, true, false);
+            content.setBackground(bg);
+        }
+
+        root.addView(cling);
+
+        if (showWelcome) {
+            // This is the first cling being shown. No need to animate.
+            return;
+        }
+
+        // Animate
+        content.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+
+            @Override
+            public void onGlobalLayout() {
+                content.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+
+                ObjectAnimator anim;
+                if (TAG_CROP_TOP_AND_SIDES.equals(content.getTag())) {
+                    content.setTranslationY(-content.getMeasuredHeight());
+                    anim = LauncherAnimUtils.ofFloat(content, "translationY", 0);
+                } else {
+                    content.setScaleX(0);
+                    content.setScaleY(0);
+                    PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1);
+                    PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1);
+                    anim = LauncherAnimUtils.ofPropertyValuesHolder(content, scaleX, scaleY);
+                }
+
+                anim.setDuration(SHOW_CLING_DURATION);
+                anim.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                anim.start();
+            }
+        });
+    }
+
+    private void dismissLongPressCling() {
+        Runnable dismissCb = new Runnable() {
+            public void run() {
+                dismissCling(mLauncher.findViewById(R.id.longpress_cling), null,
+                        WORKSPACE_CLING_DISMISSED_KEY, DISMISS_CLING_DURATION);
+            }
+        };
+        mLauncher.getWorkspace().post(dismissCb);
+    }
+
+    /** Hides the specified Cling */
+    private void dismissCling(final View cling, final Runnable postAnimationCb,
+                              final String flag, int duration) {
+        // To catch cases where siblings of top-level views are made invisible, just check whether
+        // the cling is directly set to GONE before dismissing it.
+        if (cling != null && cling.getVisibility() != View.GONE) {
+            final Runnable cleanUpClingCb = new Runnable() {
+                public void run() {
+                    cling.setVisibility(View.GONE);
+                    mLauncher.getSharedPrefs().edit()
+                        .putBoolean(flag, true)
+                        .apply();
+                    if (postAnimationCb != null) {
+                        postAnimationCb.run();
+                    }
+                }
+            };
+            if (duration <= 0) {
+                cleanUpClingCb.run();
+            } else {
+                cling.animate().alpha(0).setDuration(duration).withEndAction(cleanUpClingCb);
             }
         }
-        return cling;
     }
 
     /** Returns whether the clings are enabled or should be shown */
-    private boolean isClingsEnabled() {
+    private boolean areClingsEnabled() {
         if (DISABLE_CLINGS) {
             return false;
         }
 
-        // For now, limit only to phones
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        if (grid.isTablet()) {
-            return false;
-        }
-        if (grid.isLandscape) {
-            return false;
-        }
-
         // disable clings when running in a test harness
         if(ActivityManager.isRunningInTestHarness()) return false;
 
@@ -113,344 +239,25 @@
                 return false;
             }
         }
+        if (Settings.Secure.getInt(mLauncher.getContentResolver(), SKIP_FIRST_USE_HINTS, 0)
+                == 1) {
+            return false;
+        }
         return true;
     }
 
-    /** Returns whether the folder cling is visible. */
-    public boolean isFolderClingVisible() {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
-        if (cling != null) {
-            return cling.getVisibility() == View.VISIBLE;
-        }
-        return false;
-    }
-
-    private boolean skipCustomClingIfNoAccounts() {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
-        boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
-        if (customCling) {
-            AccountManager am = AccountManager.get(mLauncher);
-            if (am == null) return false;
-            Account[] accounts = am.getAccountsByType("com.google");
-            return accounts.length == 0;
-        }
-        return false;
-    }
-
-    /** Updates the first run cling custom content hint */
-    private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible,
-                                                boolean animate) {
-        final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint);
-        if (ccHint != null) {
-            if (visible && !ccHintStr.isEmpty()) {
-                ccHint.setText(ccHintStr);
-                ccHint.setVisibility(View.VISIBLE);
-                if (animate) {
-                    ccHint.setAlpha(0f);
-                    ccHint.animate().alpha(1f)
-                            .setDuration(SHOW_CLING_DURATION)
-                            .start();
-                } else {
-                    ccHint.setAlpha(1f);
-                }
-            } else {
-                if (animate) {
-                    ccHint.animate().alpha(0f)
-                            .setDuration(SHOW_CLING_DURATION)
-                            .setListener(new AnimatorListenerAdapter() {
-                                @Override
-                                public void onAnimationEnd(Animator animation) {
-                                    ccHint.setVisibility(View.GONE);
-                                }
-                            })
-                            .start();
-                } else {
-                    ccHint.setAlpha(0f);
-                    ccHint.setVisibility(View.GONE);
-                }
-            }
-        }
-    }
-
-    /** Updates the first run cling custom content hint */
-    public void updateCustomContentHintVisibility() {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
-        String ccHintStr = mLauncher.getFirstRunCustomContentHint();
-
-        if (mLauncher.getWorkspace().hasCustomContent()) {
-            // Show the custom content hint if ccHintStr is not empty
-            if (cling != null) {
-                setCustomContentHintVisibility(cling, ccHintStr, true, true);
-            }
-        } else {
-            // Hide the custom content hint
-            if (cling != null) {
-                setCustomContentHintVisibility(cling, ccHintStr, false, true);
-            }
-        }
-    }
-
-    /** Updates the first run cling search bar hint. */
-    public void updateSearchBarHint(String hint) {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
-        if (cling != null && cling.getVisibility() == View.VISIBLE && !hint.isEmpty()) {
-            TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
-            sbHint.setText(hint);
-            sbHint.setVisibility(View.VISIBLE);
-        }
-    }
-
     public boolean shouldShowFirstRunOrMigrationClings() {
         SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
-        return isClingsEnabled() &&
-            !sharedPrefs.getBoolean(FIRST_RUN_CLING_DISMISSED_KEY, false) &&
+        return areClingsEnabled() &&
+            !sharedPrefs.getBoolean(WORKSPACE_CLING_DISMISSED_KEY, false) &&
             !sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false);
     }
 
-    public void removeFirstRunAndMigrationClings() {
-        removeCling(R.id.first_run_cling);
-        removeCling(R.id.migration_cling);
-    }
-
-    /**
-     * Shows the first run cling.
-     *
-     * This flow is mutually exclusive with showMigrationCling, and only runs if this Launcher
-     * package was preinstalled or there is no db to migrate from.
-     */
-    public void showFirstRunCling() {
-        if (!skipCustomClingIfNoAccounts()) {
-            SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
-            // If we're not using the default workspace layout, replace workspace cling
-            // with a custom workspace cling (usually specified in an overlay)
-            // For now, only do this on tablets
-            if (!DISABLE_CUSTOM_CLINGS) {
-                if (sharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
-                        mLauncher.getResources().getBoolean(R.bool.config_useCustomClings)) {
-                    // Use a custom cling
-                    View cling = mLauncher.findViewById(R.id.workspace_cling);
-                    ViewGroup clingParent = (ViewGroup) cling.getParent();
-                    int clingIndex = clingParent.indexOfChild(cling);
-                    clingParent.removeViewAt(clingIndex);
-                    View customCling = mInflater.inflate(R.layout.custom_workspace_cling,
-                            clingParent, false);
-                    clingParent.addView(customCling, clingIndex);
-                    customCling.setId(R.id.workspace_cling);
-                }
-            }
-            Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
-            if (cling != null) {
-                String sbHintStr = mLauncher.getFirstRunClingSearchBarHint();
-                String ccHintStr = mLauncher.getFirstRunCustomContentHint();
-                if (!sbHintStr.isEmpty()) {
-                    TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
-                    sbHint.setText(sbHintStr);
-                    sbHint.setVisibility(View.VISIBLE);
-                }
-                setCustomContentHintVisibility(cling, ccHintStr, true, false);
-            }
-            initCling(R.id.first_run_cling, 0, false, true);
-        } else {
-            removeFirstRunAndMigrationClings();
-        }
-    }
-
-    /**
-     * Shows the migration cling.
-     *
-     * This flow is mutually exclusive with showFirstRunCling, and only runs if this Launcher
-     * package was not preinstalled and there exists a db to migrate from.
-     */
-    public void showMigrationCling() {
-        mLauncher.hideWorkspaceSearchAndHotseat();
-
-        Cling c = initCling(R.id.migration_cling, 0, false, true);
-        c.bringScrimToFront();
-        c.bringToFront();
-    }
-
-    public void showMigrationWorkspaceCling() {
-        // Enable the clings only if they have not been dismissed before
-        if (isClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
-                MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, false)) {
-            Cling c = initCling(R.id.migration_workspace_cling, 0, false, true);
-            c.updateMigrationWorkspaceBubblePosition();
-            c.bringScrimToFront();
-            c.bringToFront();
-        } else {
-            removeCling(R.id.migration_workspace_cling);
-        }
-    }
-
-    public void showWorkspaceCling() {
-        // Enable the clings only if they have not been dismissed before
-        if (isClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
-                WORKSPACE_CLING_DISMISSED_KEY, false)) {
-            Cling c = initCling(R.id.workspace_cling, 0, false, true);
-
-            // Set the focused hotseat app if there is one
-            c.setFocusedHotseatApp(mLauncher.getFirstRunFocusedHotseatAppDrawableId(),
-                    mLauncher.getFirstRunFocusedHotseatAppRank(),
-                    mLauncher.getFirstRunFocusedHotseatAppComponentName(),
-                    mLauncher.getFirstRunFocusedHotseatAppBubbleTitle(),
-                    mLauncher.getFirstRunFocusedHotseatAppBubbleDescription());
-        } else {
-            removeCling(R.id.workspace_cling);
-        }
-    }
-    public Cling showFoldersCling() {
-        SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
-        // Enable the clings only if they have not been dismissed before
-        if (isClingsEnabled() &&
-                !sharedPrefs.getBoolean(FOLDER_CLING_DISMISSED_KEY, false) &&
-                !sharedPrefs.getBoolean(Launcher.USER_HAS_MIGRATED, false)) {
-            Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
-                    true, true);
-            return cling;
-        } else {
-            removeCling(R.id.folder_cling);
-            return null;
-        }
-    }
-
-    /** Removes the cling outright from the DragLayer */
-    private void removeCling(int id) {
-        final View cling = mLauncher.findViewById(id);
-        if (cling != null) {
-            final ViewGroup parent = (ViewGroup) cling.getParent();
-            parent.post(new Runnable() {
-                @Override
-                public void run() {
-                    parent.removeView(cling);
-                }
-            });
-            mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
-        }
-    }
-
-    /** Hides the specified Cling */
-    private void dismissCling(final Cling cling, final Runnable postAnimationCb,
-                              final String flag, int duration, boolean restoreNavBarVisibilty) {
-        // To catch cases where siblings of top-level views are made invisible, just check whether
-        // the cling is directly set to GONE before dismissing it.
-        if (cling != null && cling.getVisibility() != View.GONE) {
-            final Runnable cleanUpClingCb = new Runnable() {
-                public void run() {
-                    cling.cleanup();
-                    SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit();
-                    editor.putBoolean(flag, true);
-                    editor.apply();
-                    if (postAnimationCb != null) {
-                        postAnimationCb.run();
-                    }
-                }
-            };
-            if (duration <= 0) {
-                cleanUpClingCb.run();
-            } else {
-                cling.hide(duration, cleanUpClingCb);
-            }
-            mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
-
-            if (restoreNavBarVisibilty) {
-                cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
-                        ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
-            }
-        }
-    }
-
-    public void dismissFirstRunCling(View v) {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
-        Runnable cb = new Runnable() {
-            public void run() {
-                // Show the workspace cling next
-                showWorkspaceCling();
-            }
-        };
-        dismissCling(cling, cb, FIRST_RUN_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, false);
-
-        // Fade out the search bar for the workspace cling coming up
-        mLauncher.getSearchBar().hideSearchBar(true);
-    }
-
-    private void dismissMigrationCling() {
-        mLauncher.showWorkspaceSearchAndHotseat();
-        Runnable dismissCb = new Runnable() {
-            public void run() {
-                Cling cling = (Cling) mLauncher.findViewById(R.id.migration_cling);
-                Runnable cb = new Runnable() {
-                    public void run() {
-                        // Show the migration workspace cling next
-                        showMigrationWorkspaceCling();
-                    }
-                };
-                dismissCling(cling, cb, WORKSPACE_CLING_DISMISSED_KEY,
-                        DISMISS_CLING_DURATION, true);
-            }
-        };
-        mLauncher.getWorkspace().post(dismissCb);
-    }
-
-    private void dismissAnyWorkspaceCling(Cling cling, View v) {
-        Runnable cb = null;
-        if (v == null) {
-            cb = new Runnable() {
-                public void run() {
-                    mLauncher.getWorkspace().enterOverviewMode();
-                }
-            };
-        }
-        dismissCling(cling, cb, WORKSPACE_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, true);
-
-        // Fade in the search bar
-        mLauncher.getSearchBar().showSearchBar(true);
-    }
-
-    public void dismissMigrationClingCopyApps(View v) {
-        // Copy the shortcuts from the old database
-        LauncherModel model = mLauncher.getModel();
-        model.resetLoadedState(false, true);
-        model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
-                LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
-                        | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
-
-        // Set the flag to skip the folder cling
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-        SharedPreferences.Editor editor = sp.edit();
-        editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
-        editor.apply();
-
-        // Disable the migration cling
-        dismissMigrationCling();
-    }
-
-    public void dismissMigrationClingUseDefault(View v) {
-        // Clear the workspace
-        LauncherModel model = mLauncher.getModel();
-        model.resetLoadedState(false, true);
-        model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
-                LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
-
-        // Disable the migration cling
-        dismissMigrationCling();
-    }
-
-    public void dismissMigrationWorkspaceCling(View v) {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.migration_workspace_cling);
-        dismissAnyWorkspaceCling(cling, v);
-    }
-
-    public void dismissWorkspaceCling(View v) {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
-        dismissAnyWorkspaceCling(cling, v);
-    }
-
-    public void dismissFolderCling(View v) {
-        Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
-        dismissCling(cling, null, FOLDER_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, true);
+    public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) {
+        SharedPreferences prefs = ctx.getSharedPreferences(
+                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = prefs.edit();
+        editor.putBoolean(WORKSPACE_CLING_DISMISSED_KEY, true);
+        editor.commit();
     }
 }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 4478e9b..c64506d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -19,12 +19,19 @@
 import android.app.SearchManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
-import android.content.*;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
 import android.content.Intent.ShortcutIconResource;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageInfo;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -44,10 +51,17 @@
 import android.util.Log;
 import android.util.Pair;
 
-import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
 
 import java.lang.ref.WeakReference;
 import java.net.URISyntaxException;
+import java.security.InvalidParameterException;
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -58,6 +72,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -67,14 +82,17 @@
  * LauncherModel object held in a static. Also provide APIs for updating the database state
  * for the Launcher.
  */
-public class LauncherModel extends BroadcastReceiver {
+public class LauncherModel extends BroadcastReceiver
+        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
     static final boolean DEBUG_LOADERS = false;
+    private static final boolean DEBUG_RECEIVER = false;
+    private static final boolean REMOVE_UNRESTORED_ICONS = true;
+
     static final String TAG = "Launcher.Model";
 
     // true = use a "More Apps" folder for non-workspace apps on upgrade
     // false = strew non-workspace apps across the workspace on upgrade
     public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;
-
     public static final int LOADER_FLAG_NONE = 0;
     public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
     public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
@@ -97,6 +115,7 @@
     private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;
     private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;
 
+    private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";
 
     private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
     static {
@@ -149,13 +168,19 @@
     // sBgWorkspaceScreens is the ordered set of workspace screens.
     static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
 
+    // sPendingPackages is a set of packages which could be on sdcard and are not available yet
+    static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =
+            new HashMap<UserHandleCompat, HashSet<String>>();
+
     // </ only access in worker thread >
 
     private IconCache mIconCache;
-    private Bitmap mDefaultIcon;
 
     protected int mPreviousConfigMcc;
 
+    private final LauncherAppsCompat mLauncherApps;
+    private final UserManagerCompat mUserManager;
+
     public interface Callbacks {
         public boolean setLoadOnResume();
         public int getCurrentWorkspaceScreen();
@@ -173,8 +198,11 @@
                                   ArrayList<ItemInfo> addAnimated,
                                   ArrayList<AppInfo> addedApps);
         public void bindAppsUpdated(ArrayList<AppInfo> apps);
+        public void bindAppsRestored(ArrayList<AppInfo> apps);
+        public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
+        public void updatePackageBadge(String packageName);
         public void bindComponentsRemoved(ArrayList<String> packageNames,
-                        ArrayList<AppInfo> appInfos);
+                        ArrayList<AppInfo> appInfos, UserHandleCompat user);
         public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
         public void bindSearchablesChanged();
         public boolean isAllAppsButtonRank(int rank);
@@ -188,11 +216,26 @@
 
     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
         Context context = app.getContext();
-        ContentResolver contentResolver = context.getContentResolver();
 
         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
-        mOldContentProviderExists = (contentResolver.acquireContentProviderClient(
-                LauncherSettings.Favorites.OLD_CONTENT_URI) != null);
+        String oldProvider = context.getString(R.string.old_launcher_provider_uri);
+        // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different
+        // resource string.
+        String redirectAuthority = Uri.parse(oldProvider).getAuthority();
+        ProviderInfo providerInfo =
+                context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY, 0);
+        ProviderInfo redirectProvider =
+                context.getPackageManager().resolveContentProvider(redirectAuthority, 0);
+
+        Log.d(TAG, "Old launcher provider: " + oldProvider);
+        mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);
+
+        if (mOldContentProviderExists) {
+            Log.d(TAG, "Old launcher provider exists.");
+        } else {
+            Log.d(TAG, "Old launcher provider does not exist.");
+        }
+
         mApp = app;
         mBgAllAppsList = new AllAppsList(iconCache, appFilter);
         mIconCache = iconCache;
@@ -200,6 +243,8 @@
         final Resources res = context.getResources();
         Configuration config = res.getConfiguration();
         mPreviousConfigMcc = config.mcc;
+        mLauncherApps = LauncherAppsCompat.getInstance(context);
+        mUserManager = UserManagerCompat.getInstance(context);
     }
 
     /** Runs the specified runnable immediately if called from the main thread, otherwise it is
@@ -292,17 +337,85 @@
         return null;
     }
 
-    public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,
-                                    final ArrayList<AppInfo> allAppsApps) {
-        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
-        addAndBindAddedApps(context, workspaceApps, cb, allAppsApps);
+    public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {
+        // Process the updated package state
+        Runnable r = new Runnable() {
+            public void run() {
+                Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+                if (callbacks != null) {
+                    callbacks.updatePackageState(installInfo);
+                }
+            }
+        };
+        mHandler.post(r);
     }
-    public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,
-                                final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) {
-        if (workspaceApps == null || allAppsApps == null) {
+
+    public void updatePackageBadge(final String packageName) {
+        // Process the updated package badge
+        Runnable r = new Runnable() {
+            public void run() {
+                Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+                if (callbacks != null) {
+                    callbacks.updatePackageBadge(packageName);
+                }
+            }
+        };
+        mHandler.post(r);
+    }
+
+    public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
+        final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+
+        if (allAppsApps == null) {
+            throw new RuntimeException("allAppsApps must not be null");
+        }
+        if (allAppsApps.isEmpty()) {
+            return;
+        }
+
+        final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
+        Iterator<AppInfo> iter = allAppsApps.iterator();
+        while (iter.hasNext()) {
+            ItemInfo a = iter.next();
+            if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {
+                restoredAppsFinal.add((AppInfo) a);
+            }
+        }
+
+        // Process the newly added applications and add them to the database first
+        Runnable r = new Runnable() {
+            public void run() {
+                runOnMainThread(new Runnable() {
+                    public void run() {
+                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                        if (callbacks == cb && cb != null) {
+                            if (!restoredAppsFinal.isEmpty()) {
+                                for (AppInfo info : restoredAppsFinal) {
+                                    final Intent intent = info.getIntent();
+                                    if (intent != null) {
+                                        mIconCache.deletePreloadedIcon(intent.getComponent(),
+                                                info.user);
+                                    }
+                                }
+                                callbacks.bindAppsUpdated(restoredAppsFinal);
+                            }
+                            callbacks.bindAppsAdded(null, null, null, allAppsApps);
+                        }
+                    }
+                });
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    public void addAndBindAddedWorkspaceApps(final Context context,
+            final ArrayList<ItemInfo> workspaceApps) {
+        final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+
+        if (workspaceApps == null) {
             throw new RuntimeException("workspaceApps and allAppsApps must not be null");
         }
-        if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) {
+        if (workspaceApps.isEmpty()) {
             return;
         }
         // Process the newly added applications and add them to the database first
@@ -310,6 +423,7 @@
             public void run() {
                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
+                final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
 
                 // Get the list of workspace screens.  We need to append to this list and
                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
@@ -330,6 +444,11 @@
 
                         // Short-circuit this logic if the icon exists somewhere on the workspace
                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {
+                            // Only InstallShortcutReceiver sends us shortcutInfos, ignore them
+                            if (a instanceof AppInfo &&
+                                    LauncherModel.appWasPromise(context, launchIntent, a.user)) {
+                                restoredAppsFinal.add((AppInfo) a);
+                            }
                             continue;
                         }
 
@@ -385,7 +504,7 @@
                 // Update the workspace screens
                 updateWorkspaceScreenOrder(context, workspaceScreens);
 
-                if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) {
+                if (!addedShortcutsFinal.isEmpty()) {
                     runOnMainThread(new Runnable() {
                         public void run() {
                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
@@ -404,7 +523,10 @@
                                     }
                                 }
                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
-                                        addNotAnimated, addAnimated, allAppsApps);
+                                        addNotAnimated, addAnimated, null);
+                                if (!restoredAppsFinal.isEmpty()) {
+                                    callbacks.bindAppsUpdated(restoredAppsFinal);
+                                }
                             }
                         }
                     });
@@ -414,15 +536,6 @@
         runOnWorkerThread(r);
     }
 
-    public Bitmap getFallbackIcon() {
-        if (mDefaultIcon == null) {
-            final Context context = LauncherAppState.getInstance().getContext();
-            mDefaultIcon = Utilities.createIconBitmap(
-                    mIconCache.getFullResDefaultActivityIcon(), context);
-        }
-        return Bitmap.createBitmap(mDefaultIcon);
-    }
-
     public void unbindItemInfosAndClearQueuedBindRunnables() {
         if (sWorkerThread.getThreadId() == Process.myTid()) {
             throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +
@@ -430,7 +543,9 @@
         }
 
         // Clear any deferred bind runnables
-        mDeferredBindRunnables.clear();
+        synchronized (mDeferredBindRunnables) {
+            mDeferredBindRunnables.clear();
+        }
         // Remove any queued bind runnables
         mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);
         // Unbind all the workspace items
@@ -746,7 +861,7 @@
      */
     static void updateItemInDatabase(Context context, final ItemInfo item) {
         final ContentValues values = new ContentValues();
-        item.onAddToDatabase(values);
+        item.onAddToDatabase(context, values);
         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
         updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
     }
@@ -757,9 +872,26 @@
      */
     static boolean shortcutExists(Context context, String title, Intent intent) {
         final ContentResolver cr = context.getContentResolver();
+        final Intent intentWithPkg, intentWithoutPkg;
+
+        if (intent.getComponent() != null) {
+            // If component is not null, an intent with null package will produce
+            // the same result and should also be a match.
+            if (intent.getPackage() != null) {
+                intentWithPkg = intent;
+                intentWithoutPkg = new Intent(intent).setPackage(null);
+            } else {
+                intentWithPkg = new Intent(intent).setPackage(
+                        intent.getComponent().getPackageName());
+                intentWithoutPkg = intent;
+            }
+        } else {
+            intentWithPkg = intent;
+            intentWithoutPkg = intent;
+        }
         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
-            new String[] { "title", "intent" }, "title=? and intent=?",
-            new String[] { title, intent.toUri(0) }, null);
+            new String[] { "title", "intent" }, "title=? and (intent=? or intent=?)",
+            new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0) }, null);
         boolean result = false;
         try {
             result = c.moveToFirst();
@@ -770,6 +902,17 @@
     }
 
     /**
+     * Returns true if the promise shortcuts with the same package name exists on the workspace.
+     */
+    static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {
+        final ComponentName component = intent.getComponent();
+        if (component == null) {
+            return false;
+        }
+        return !getItemsByPackageName(component.getPackageName(), user).isEmpty();
+    }
+
+    /**
      * Returns an ItemInfo array containing all the items in the LauncherModel.
      * The ItemInfo.id is not set through this function.
      */
@@ -778,8 +921,10 @@
         final ContentResolver cr = context.getContentResolver();
         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {
                 LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,
-                LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
-                LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY }, null, null, null);
+                LauncherSettings.Favorites.SCREEN,
+                LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
+                LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY,
+                LauncherSettings.Favorites.PROFILE_ID }, null, null, null);
 
         final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
         final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
@@ -788,7 +933,8 @@
         final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
         final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
         final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
-
+        final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);
+        UserManagerCompat userManager = UserManagerCompat.getInstance(context);
         try {
             while (c.moveToNext()) {
                 ItemInfo item = new ItemInfo();
@@ -799,8 +945,12 @@
                 item.container = c.getInt(containerIndex);
                 item.itemType = c.getInt(itemTypeIndex);
                 item.screenId = c.getInt(screenIndex);
-
-                items.add(item);
+                long serialNumber = c.getInt(profileIdIndex);
+                item.user = userManager.getUserForSerialNumber(serialNumber);
+                // Skip if user has been deleted.
+                if (item.user != null) {
+                    items.add(item);
+                }
             }
         } catch (Exception e) {
             items.clear();
@@ -873,12 +1023,13 @@
 
         final ContentValues values = new ContentValues();
         final ContentResolver cr = context.getContentResolver();
-        item.onAddToDatabase(values);
+        item.onAddToDatabase(context, values);
 
         item.id = LauncherAppState.getLauncherProvider().generateNewItemId();
         values.put(LauncherSettings.Favorites._ID, item.id);
         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
 
+        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
         Runnable r = new Runnable() {
             public void run() {
                 cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
@@ -886,7 +1037,7 @@
 
                 // Lock on mBgLock *after* the db operation
                 synchronized (sBgLock) {
-                    checkItemInfoLocked(item.id, item, null);
+                    checkItemInfoLocked(item.id, item, stackTrace);
                     sBgItemsIdMap.put(item.id, item);
                     switch (item.itemType) {
                         case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
@@ -925,45 +1076,77 @@
                 | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
     }
 
+    private static ArrayList<ItemInfo> getItemsByPackageName(
+            final String pn, final UserHandleCompat user) {
+        ItemInfoFilter filter  = new ItemInfoFilter() {
+            @Override
+            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
+                return cn.getPackageName().equals(pn) && info.user.equals(user);
+            }
+        };
+        return filterItemInfos(sBgItemsIdMap.values(), filter);
+    }
+
+    /**
+     * Removes all the items from the database corresponding to the specified package.
+     */
+    static void deletePackageFromDatabase(Context context, final String pn,
+            final UserHandleCompat user) {
+        deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));
+    }
+
     /**
      * Removes the specified item from the database
      * @param context
      * @param item
      */
     static void deleteItemFromDatabase(Context context, final ItemInfo item) {
+        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
+        items.add(item);
+        deleteItemsFromDatabase(context, items);
+    }
+
+    /**
+     * Removes the specified items from the database
+     * @param context
+     * @param item
+     */
+    static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {
         final ContentResolver cr = context.getContentResolver();
-        final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);
 
         Runnable r = new Runnable() {
             public void run() {
-                cr.delete(uriToDelete, null, null);
+                for (ItemInfo item : items) {
+                    final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
+                    cr.delete(uri, null, null);
 
-                // Lock on mBgLock *after* the db operation
-                synchronized (sBgLock) {
-                    switch (item.itemType) {
-                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
-                            sBgFolders.remove(item.id);
-                            for (ItemInfo info: sBgItemsIdMap.values()) {
-                                if (info.container == item.id) {
-                                    // We are deleting a folder which still contains items that
-                                    // think they are contained by that folder.
-                                    String msg = "deleting a folder (" + item + ") which still " +
-                                            "contains items (" + info + ")";
-                                    Log.e(TAG, msg);
+                    // Lock on mBgLock *after* the db operation
+                    synchronized (sBgLock) {
+                        switch (item.itemType) {
+                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                                sBgFolders.remove(item.id);
+                                for (ItemInfo info: sBgItemsIdMap.values()) {
+                                    if (info.container == item.id) {
+                                        // We are deleting a folder which still contains items that
+                                        // think they are contained by that folder.
+                                        String msg = "deleting a folder (" + item + ") which still " +
+                                                "contains items (" + info + ")";
+                                        Log.e(TAG, msg);
+                                    }
                                 }
-                            }
-                            sBgWorkspaceItems.remove(item);
-                            break;
-                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
-                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
-                            sBgWorkspaceItems.remove(item);
-                            break;
-                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
-                            sBgAppWidgets.remove((LauncherAppWidgetInfo) item);
-                            break;
+                                sBgWorkspaceItems.remove(item);
+                                break;
+                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                                sBgWorkspaceItems.remove(item);
+                                break;
+                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                                sBgAppWidgets.remove((LauncherAppWidgetInfo) item);
+                                break;
+                        }
+                        sBgItemsIdMap.remove(item.id);
+                        sBgDbIconCache.remove(item);
                     }
-                    sBgItemsIdMap.remove(item.id);
-                    sBgDbIconCache.remove(item);
                 }
             }
         };
@@ -995,18 +1178,23 @@
         Runnable r = new Runnable() {
             @Override
             public void run() {
+                ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
                 // Clear the table
-                cr.delete(uri, null, null);
+                ops.add(ContentProviderOperation.newDelete(uri).build());
                 int count = screensCopy.size();
-                ContentValues[] values = new ContentValues[count];
                 for (int i = 0; i < count; i++) {
                     ContentValues v = new ContentValues();
                     long screenId = screensCopy.get(i);
                     v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
                     v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
-                    values[i] = v;
+                    ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
                 }
-                cr.bulkInsert(uri, values);
+
+                try {
+                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }
 
                 synchronized (sBgLock) {
                     sBgWorkspaceScreens.clear();
@@ -1057,74 +1245,67 @@
         }
     }
 
+    @Override
+    public void onPackageChanged(String packageName, UserHandleCompat user) {
+        int op = PackageUpdatedTask.OP_UPDATE;
+        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
+                user));
+    }
+
+    @Override
+    public void onPackageRemoved(String packageName, UserHandleCompat user) {
+        int op = PackageUpdatedTask.OP_REMOVE;
+        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
+                user));
+    }
+
+    @Override
+    public void onPackageAdded(String packageName, UserHandleCompat user) {
+        int op = PackageUpdatedTask.OP_ADD;
+        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
+                user));
+    }
+
+    @Override
+    public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,
+            boolean replacing) {
+        if (!replacing) {
+            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames,
+                    user));
+            if (mAppsCanBeOnRemoveableStorage) {
+                // Only rebind if we support removable storage. It catches the
+                // case where
+                // apps on the external sd card need to be reloaded
+                startLoaderFromBackground();
+            }
+        } else {
+            // If we are replacing then just update the packages in the list
+            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,
+                    packageNames, user));
+        }
+    }
+
+    @Override
+    public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,
+            boolean replacing) {
+        if (!replacing) {
+            enqueuePackageUpdated(new PackageUpdatedTask(
+                    PackageUpdatedTask.OP_UNAVAILABLE, packageNames,
+                    user));
+        }
+
+    }
+
     /**
      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
      * ACTION_PACKAGE_CHANGED.
      */
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);
+        if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
 
         final String action = intent.getAction();
-
-        if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
-                || Intent.ACTION_PACKAGE_REMOVED.equals(action)
-                || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-            final String packageName = intent.getData().getSchemeSpecificPart();
-            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-
-            int op = PackageUpdatedTask.OP_NONE;
-
-            if (packageName == null || packageName.length() == 0) {
-                // they sent us a bad intent
-                return;
-            }
-
-            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-                op = PackageUpdatedTask.OP_UPDATE;
-            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                if (!replacing) {
-                    op = PackageUpdatedTask.OP_REMOVE;
-                }
-                // else, we are replacing the package, so a PACKAGE_ADDED will be sent
-                // later, we will update the package at this time
-            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-                if (!replacing) {
-                    op = PackageUpdatedTask.OP_ADD;
-                } else {
-                    op = PackageUpdatedTask.OP_UPDATE;
-                }
-            }
-
-            if (op != PackageUpdatedTask.OP_NONE) {
-                enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName }));
-            }
-
-        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
-            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            if (!replacing) {
-                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
-                if (mAppsCanBeOnRemoveableStorage) {
-                    // Only rebind if we support removable storage.  It catches the case where
-                    // apps on the external sd card need to be reloaded
-                    startLoaderFromBackground();
-                }
-            } else {
-                // If we are replacing then just update the packages in the list
-                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,
-                        packages));
-            }
-        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-            if (!replacing) {
-                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-                enqueuePackageUpdated(new PackageUpdatedTask(
-                            PackageUpdatedTask.OP_UNAVAILABLE, packages));
-            }
-            // else, we are replacing the packages, so ignore this event and wait for
-            // EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time
-        } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+        if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
             // If we have changed locale we need to clear out the labels in all apps/workspace.
             forceReload();
         } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
@@ -1150,7 +1331,7 @@
         }
     }
 
-    private void forceReload() {
+    void forceReload() {
         resetLoadedState(true, true);
 
         // Do this here because if the launcher activity is running it will be restarted.
@@ -1205,6 +1386,10 @@
         return isLaunching;
     }
 
+    public boolean isCurrentCallbacks(Callbacks callbacks) {
+        return (mCallbacks != null && mCallbacks.get() == callbacks);
+    }
+
     public void startLoader(boolean isLaunching, int synchronousBindPage) {
         startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);
     }
@@ -1217,7 +1402,9 @@
 
             // Clear any deferred bind-runnables from the synchronized load process
             // We must do this before any loading/binding is scheduled below.
-            mDeferredBindRunnables.clear();
+            synchronized (mDeferredBindRunnables) {
+                mDeferredBindRunnables.clear();
+            }
 
             // Don't bother to start the thread if we know it's not going to do anything
             if (mCallbacks != null && mCallbacks.get() != null) {
@@ -1239,10 +1426,15 @@
     void bindRemainingSynchronousPages() {
         // Post the remaining side pages to be loaded
         if (!mDeferredBindRunnables.isEmpty()) {
-            for (final Runnable r : mDeferredBindRunnables) {
+            Runnable[] deferredBindRunnables = null;
+            synchronized (mDeferredBindRunnables) {
+                deferredBindRunnables = mDeferredBindRunnables.toArray(
+                        new Runnable[mDeferredBindRunnables.size()]);
+                mDeferredBindRunnables.clear();
+            }
+            for (final Runnable r : deferredBindRunnables) {
                 mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);
             }
-            mDeferredBindRunnables.clear();
         }
     }
 
@@ -1551,7 +1743,7 @@
             ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
             synchronized (sBgLock) {
                 for (AppInfo app : mBgAllAppsList.data) {
-                    tmpInfos = getItemInfoForComponentName(app.componentName);
+                    tmpInfos = getItemInfoForComponentName(app.componentName, app.user);
                     if (tmpInfos.isEmpty()) {
                         // We are missing an application icon, so add this to the workspace
                         added.add(app);
@@ -1561,8 +1753,7 @@
                 }
             }
             if (!added.isEmpty()) {
-                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
-                addAndBindAddedApps(context, added, cb, new ArrayList<AppInfo>());
+                addAndBindAddedWorkspaceApps(context, added);
             }
         }
 
@@ -1682,6 +1873,9 @@
             final PackageManager manager = context.getPackageManager();
             final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
             final boolean isSafeMode = manager.isSafeMode();
+            final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+            final boolean isSdCardReady = context.registerReceiver(null,
+                    new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;
 
             LauncherAppState app = LauncherAppState.getInstance();
             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -1700,21 +1894,23 @@
             } else {
                 // Make sure the default workspace is loaded
                 Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
-                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
             }
 
-            // Check if we need to do any upgrade-path logic
-            // (Includes having just imported default favorites)
-            boolean loadedOldDb = LauncherAppState.getLauncherProvider().justLoadedOldDb();
+            // This code path is for our old migration code and should no longer be exercised
+            boolean loadedOldDb = false;
 
             // Log to disk
             Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);
 
             synchronized (sBgLock) {
                 clearSBgDataStructures();
+                final HashSet<String> installingPkgs = PackageInstallerCompat
+                        .getInstance(mContext).updateAndGetActiveSessionCache();
 
                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
-                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
+                final ArrayList<Long> restoredRows = new ArrayList<Long>();
+                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;
                 if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);
 
@@ -1754,6 +1950,10 @@
                             (LauncherSettings.Favorites.SPANX);
                     final int spanYIndex = c.getColumnIndexOrThrow(
                             LauncherSettings.Favorites.SPANY);
+                    final int restoredIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.RESTORED);
+                    final int profileIdIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.PROFILE_ID);
                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
                     //final int displayModeIndex = c.getColumnIndexOrThrow(
                     //        LauncherSettings.Favorites.DISPLAY_MODE);
@@ -1764,41 +1964,144 @@
                     int container;
                     long id;
                     Intent intent;
+                    UserHandleCompat user;
 
                     while (!mStopped && c.moveToNext()) {
                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);
                         try {
                             int itemType = c.getInt(itemTypeIndex);
+                            boolean restored = 0 != c.getInt(restoredIndex);
+                            boolean allowMissingTarget = false;
 
                             switch (itemType) {
                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                                 id = c.getLong(idIndex);
                                 intentDescription = c.getString(intentIndex);
+                                long serialNumber = c.getInt(profileIdIndex);
+                                user = mUserManager.getUserForSerialNumber(serialNumber);
+                                int promiseType = c.getInt(restoredIndex);
+                                if (user == null) {
+                                    // User has been deleted remove the item.
+                                    itemsToRemove.add(id);
+                                    continue;
+                                }
                                 try {
                                     intent = Intent.parseUri(intentDescription, 0);
                                     ComponentName cn = intent.getComponent();
-                                    if (cn != null && !isValidPackageComponent(manager, cn)) {
-                                        if (!mAppsCanBeOnRemoveableStorage) {
-                                            // Log the invalid package, and remove it from the db
-                                            Launcher.addDumpLog(TAG, "Invalid package removed: " + cn, true);
+                                    if (cn != null && cn.getPackageName() != null) {
+                                        boolean validPkg = launcherApps.isPackageEnabledForProfile(
+                                                cn.getPackageName(), user);
+                                        boolean validComponent = validPkg &&
+                                                launcherApps.isActivityEnabledForProfile(cn, user);
+
+                                        if (validComponent) {
+                                            if (restored) {
+                                                // no special handling necessary for this item
+                                                restoredRows.add(id);
+                                                restored = false;
+                                            }
+                                        } else if (validPkg) {
+                                            intent = null;
+                                            if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
+                                                // We allow auto install apps to have their intent
+                                                // updated after an install.
+                                                intent = manager.getLaunchIntentForPackage(
+                                                        cn.getPackageName());
+                                                if (intent != null) {
+                                                    ContentValues values = new ContentValues();
+                                                    values.put(LauncherSettings.Favorites.INTENT,
+                                                            intent.toUri(0));
+                                                    String where = BaseColumns._ID + "= ?";
+                                                    String[] args = {Long.toString(id)};
+                                                    contentResolver.update(contentUri, values, where, args);
+                                                }
+                                            }
+
+                                            if (intent == null) {
+                                                // The app is installed but the component is no
+                                                // longer available.
+                                                Launcher.addDumpLog(TAG,
+                                                        "Invalid component removed: " + cn, true);
+                                                itemsToRemove.add(id);
+                                                continue;
+                                            } else {
+                                                // no special handling necessary for this item
+                                                restoredRows.add(id);
+                                                restored = false;
+                                            }
+                                        } else if (restored) {
+                                            // Package is not yet available but might be
+                                            // installed later.
+                                            Launcher.addDumpLog(TAG,
+                                                    "package not yet restored: " + cn, true);
+
+                                            if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
+                                                // Restore has started once.
+                                            } else if (installingPkgs.contains(cn.getPackageName())) {
+                                                // App restore has started. Update the flag
+                                                promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;
+                                                ContentValues values = new ContentValues();
+                                                values.put(LauncherSettings.Favorites.RESTORED,
+                                                        promiseType);
+                                                String where = BaseColumns._ID + "= ?";
+                                                String[] args = {Long.toString(id)};
+                                                contentResolver.update(contentUri, values, where, args);
+
+                                            } else if (REMOVE_UNRESTORED_ICONS) {
+                                                Launcher.addDumpLog(TAG,
+                                                        "Unrestored package removed: " + cn, true);
+                                                itemsToRemove.add(id);
+                                                continue;
+                                            }
+                                        } else if (isSdCardReady) {
+                                            // Do not wait for external media load anymore.
+                                            // Log the invalid package, and remove it
+                                            Launcher.addDumpLog(TAG,
+                                                    "Invalid package removed: " + cn, true);
                                             itemsToRemove.add(id);
+                                            continue;
                                         } else {
-                                            // If apps can be on external storage, then we just
-                                            // leave them for the user to remove (maybe add
-                                            // visual treatment to it)
-                                            Launcher.addDumpLog(TAG, "Invalid package found: " + cn, true);
+                                            // SdCard is not ready yet. Package might get available,
+                                            // once it is ready.
+                                            Launcher.addDumpLog(TAG, "Invalid package: " + cn
+                                                    + " (check again later)", true);
+                                            HashSet<String> pkgs = sPendingPackages.get(user);
+                                            if (pkgs == null) {
+                                                pkgs = new HashSet<String>();
+                                                sPendingPackages.put(user, pkgs);
+                                            }
+                                            pkgs.add(cn.getPackageName());
+                                            allowMissingTarget = true;
+                                            // Add the icon on the workspace anyway.
                                         }
-                                        continue;
+                                    } else if (cn == null) {
+                                        // For shortcuts with no component, keep them as they are
+                                        restoredRows.add(id);
+                                        restored = false;
                                     }
                                 } catch (URISyntaxException e) {
-                                    Launcher.addDumpLog(TAG, "Invalid uri: " + intentDescription, true);
+                                    Launcher.addDumpLog(TAG,
+                                            "Invalid uri: " + intentDescription, true);
                                     continue;
                                 }
 
-                                if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                                    info = getShortcutInfo(manager, intent, context, c, iconIndex,
-                                            titleIndex, mLabelCache);
+                                if (restored) {
+                                    if (user.equals(UserHandleCompat.myUserHandle())) {
+                                        Launcher.addDumpLog(TAG,
+                                                "constructing info for partially restored package",
+                                                true);
+                                        info = getRestoredItemInfo(c, titleIndex, intent, promiseType);
+                                        intent = getRestoredItemIntent(c, context, intent);
+                                    } else {
+                                        // Don't restore items for other profiles.
+                                        itemsToRemove.add(id);
+                                        continue;
+                                    }
+                                } else if (itemType ==
+                                        LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+                                    info = getShortcutInfo(manager, intent, user, context, c,
+                                            iconIndex, titleIndex, mLabelCache, allowMissingTarget);
                                 } else {
                                     info = getShortcutInfo(c, context, iconTypeIndex,
                                             iconPackageIndex, iconResourceIndex, iconIndex,
@@ -1827,6 +2130,9 @@
                                     info.cellY = c.getInt(cellYIndex);
                                     info.spanX = 1;
                                     info.spanY = 1;
+                                    info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
+                                    info.isDisabled = isSafeMode
+                                            && !Utilities.isSystemApp(context, intent);
 
                                     // check & update map of what's occupied
                                     deleteOnInvalidPlacement.set(false);
@@ -1890,6 +2196,11 @@
                                         break;
                                 }
 
+                                if (restored) {
+                                    // no special handling required for restored folders
+                                    restoredRows.add(id);
+                                }
+
                                 sBgItemsIdMap.put(folderInfo.id, folderInfo);
                                 sBgFolders.put(folderInfo.id, folderInfo);
                                 break;
@@ -1898,31 +2209,79 @@
                                 // Read all Launcher-specific widget details
                                 int appWidgetId = c.getInt(appWidgetIdIndex);
                                 String savedProvider = c.getString(appWidgetProviderIndex);
-
                                 id = c.getLong(idIndex);
+                                final ComponentName component =
+                                        ComponentName.unflattenFromString(savedProvider);
 
-                                final AppWidgetProviderInfo provider =
-                                        widgets.getAppWidgetInfo(appWidgetId);
+                                final int restoreStatus = c.getInt(restoredIndex);
+                                final boolean isIdValid = (restoreStatus &
+                                        LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;
 
-                                if (!isSafeMode && (provider == null || provider.provider == null ||
-                                        provider.provider.getPackageName() == null)) {
-                                    String log = "Deleting widget that isn't installed anymore: id="
-                                        + id + " appWidgetId=" + appWidgetId;
+                                final boolean wasProviderReady = (restoreStatus &
+                                        LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
+
+                                final AppWidgetProviderInfo provider = isIdValid
+                                        ? widgets.getAppWidgetInfo(appWidgetId)
+                                        : findAppWidgetProviderInfoWithComponent(context, component);
+
+                                final boolean isProviderReady = isValidProvider(provider);
+                                if (!isSafeMode && wasProviderReady && !isProviderReady) {
+                                    String log = "Deleting widget that isn't installed anymore: "
+                                            + "id=" + id + " appWidgetId=" + appWidgetId;
                                     Log.e(TAG, log);
                                     Launcher.addDumpLog(TAG, log, false);
                                     itemsToRemove.add(id);
                                 } else {
-                                    appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
-                                            provider.provider);
+                                    if (isProviderReady) {
+                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
+                                                provider.provider);
+                                        int[] minSpan =
+                                                Launcher.getMinSpanForWidget(context, provider);
+                                        appWidgetInfo.minSpanX = minSpan[0];
+                                        appWidgetInfo.minSpanY = minSpan[1];
+
+                                        int status = restoreStatus;
+                                        if (!wasProviderReady) {
+                                            // If provider was not previously ready, update the
+                                            // status and UI flag.
+
+                                            // Id would be valid only if the widget restore broadcast was received.
+                                            if (isIdValid) {
+                                                status = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+                                            } else {
+                                                status &= ~LauncherAppWidgetInfo
+                                                        .FLAG_PROVIDER_NOT_READY;
+                                            }
+                                        }
+                                        appWidgetInfo.restoreStatus = status;
+                                    } else {
+                                        Log.v(TAG, "Widget restore pending id=" + id
+                                                + " appWidgetId=" + appWidgetId
+                                                + " status =" + restoreStatus);
+                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
+                                                component);
+                                        appWidgetInfo.restoreStatus = restoreStatus;
+
+                                        if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {
+                                            // Restore has started once.
+                                        } else if (installingPkgs.contains(component.getPackageName())) {
+                                            // App restore has started. Update the flag
+                                            appWidgetInfo.restoreStatus |=
+                                                    LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
+                                        } else if (REMOVE_UNRESTORED_ICONS) {
+                                            Launcher.addDumpLog(TAG,
+                                                    "Unrestored widget removed: " + component, true);
+                                            itemsToRemove.add(id);
+                                            continue;
+                                        }
+                                    }
+
                                     appWidgetInfo.id = id;
                                     appWidgetInfo.screenId = c.getInt(screenIndex);
                                     appWidgetInfo.cellX = c.getInt(cellXIndex);
                                     appWidgetInfo.cellY = c.getInt(cellYIndex);
                                     appWidgetInfo.spanX = c.getInt(spanXIndex);
                                     appWidgetInfo.spanY = c.getInt(spanYIndex);
-                                    int[] minSpan = Launcher.getMinSpanForWidget(context, provider);
-                                    appWidgetInfo.minSpanX = minSpan[0];
-                                    appWidgetInfo.minSpanY = minSpan[1];
 
                                     container = c.getInt(containerIndex);
                                     if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
@@ -1942,13 +2301,17 @@
                                         }
                                         break;
                                     }
-                                    String providerName = provider.provider.flattenToString();
-                                    if (!providerName.equals(savedProvider)) {
+
+                                    String providerName = appWidgetInfo.providerName.flattenToString();
+                                    if (!providerName.equals(savedProvider) ||
+                                            (appWidgetInfo.restoreStatus != restoreStatus)) {
                                         ContentValues values = new ContentValues();
                                         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
                                                 providerName);
+                                        values.put(LauncherSettings.Favorites.RESTORED,
+                                                appWidgetInfo.restoreStatus);
                                         String where = BaseColumns._ID + "= ?";
-                                        String[] args = {Integer.toString(c.getInt(idIndex))};
+                                        String[] args = {Long.toString(id)};
                                         contentResolver.update(contentUri, values, where, args);
                                     }
                                     sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
@@ -1974,7 +2337,7 @@
 
                 if (itemsToRemove.size() > 0) {
                     ContentProviderClient client = contentResolver.acquireContentProviderClient(
-                            LauncherSettings.Favorites.CONTENT_URI);
+                            contentUri);
                     // Remove dead items
                     for (long id : itemsToRemove) {
                         if (DEBUG_LOADERS) {
@@ -1990,6 +2353,31 @@
                     }
                 }
 
+                if (restoredRows.size() > 0) {
+                    ContentProviderClient updater = contentResolver.acquireContentProviderClient(
+                            contentUri);
+                    // Update restored items that no longer require special handling
+                    try {
+                        StringBuilder selectionBuilder = new StringBuilder();
+                        selectionBuilder.append(LauncherSettings.Favorites._ID);
+                        selectionBuilder.append(" IN (");
+                        selectionBuilder.append(TextUtils.join(", ", restoredRows));
+                        selectionBuilder.append(")");
+                        ContentValues values = new ContentValues();
+                        values.put(LauncherSettings.Favorites.RESTORED, 0);
+                        updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
+                                values, selectionBuilder.toString(), null);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Could not update restored rows");
+                    }
+                }
+
+                if (!isSdCardReady && !sPendingPackages.isEmpty()) {
+                    context.registerReceiver(new AppsAvailabilityCheck(),
+                            new IntentFilter(StartupReceiver.SYSTEM_READY),
+                            null, sWorker);
+                }
+
                 if (loadedOldDb) {
                     long maxScreenId = 0;
                     // If we're importing we use the old screen order.
@@ -2063,7 +2451,12 @@
                                 line += " | ";
                             }
                             for (int x = 0; x < countX; x++) {
-                                line += ((occupied.get(screenId)[x][y] != null) ? "#" : ".");
+                                ItemInfo[][] screen = occupied.get(screenId);
+                                if (x < screen.length && y < screen[x].length) {
+                                    line += (screen[x][y] != null) ? "#" : ".";
+                                } else {
+                                    line += "!";
+                                }
                             }
                         }
                         Log.d(TAG, "[ " + line + " ]");
@@ -2217,7 +2610,9 @@
                     }
                 };
                 if (postOnMainThread) {
-                    deferredBindRunnables.add(r);
+                    synchronized (deferredBindRunnables) {
+                        deferredBindRunnables.add(r);
+                    }
                 } else {
                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                 }
@@ -2234,7 +2629,9 @@
                     }
                 };
                 if (postOnMainThread) {
-                    deferredBindRunnables.add(r);
+                    synchronized (deferredBindRunnables) {
+                        deferredBindRunnables.add(r);
+                    }
                 } else {
                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                 }
@@ -2356,7 +2753,9 @@
 
             // Load all the remaining pages (if we are loading synchronously, we want to defer this
             // work until after the first render)
-            mDeferredBindRunnables.clear();
+            synchronized (mDeferredBindRunnables) {
+                mDeferredBindRunnables.clear();
+            }
             bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
                     (isLoadingSynchronously ? mDeferredBindRunnables : null));
 
@@ -2378,7 +2777,9 @@
                 }
             };
             if (isLoadingSynchronously) {
-                mDeferredBindRunnables.add(r);
+                synchronized (mDeferredBindRunnables) {
+                    mDeferredBindRunnables.add(r);
+                }
             } else {
                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
             }
@@ -2444,42 +2845,42 @@
                 return;
             }
 
-            final PackageManager packageManager = mContext.getPackageManager();
             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
 
+            final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();
+
             // Clear the list of apps
             mBgAllAppsList.clear();
+            for (UserHandleCompat user : profiles) {
+                // Query for the set of apps
+                final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+                List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
+                if (DEBUG_LOADERS) {
+                    Log.d(TAG, "getActivityList took "
+                            + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);
+                    Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);
+                }
+                // Fail if we don't have any apps
+                if (apps == null || apps.isEmpty()) {
+                    return;
+                }
+                // Sort the applications by name
+                final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+                Collections.sort(apps,
+                        new LauncherModel.ShortcutNameComparator(mLabelCache));
+                if (DEBUG_LOADERS) {
+                    Log.d(TAG, "sort took "
+                            + (SystemClock.uptimeMillis()-sortTime) + "ms");
+                }
 
-            // Query for the set of apps
-            final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-            List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
-            if (DEBUG_LOADERS) {
-                Log.d(TAG, "queryIntentActivities took "
-                        + (SystemClock.uptimeMillis()-qiaTime) + "ms");
-                Log.d(TAG, "queryIntentActivities got " + apps.size() + " apps");
+                // Create the ApplicationInfos
+                for (int i = 0; i < apps.size(); i++) {
+                    LauncherActivityInfoCompat app = apps.get(i);
+                    // This builds the icon bitmaps.
+                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));
+                }
             }
-            // Fail if we don't have any apps
-            if (apps == null || apps.isEmpty()) {
-                return;
-            }
-            // Sort the applications by name
-            final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-            Collections.sort(apps,
-                    new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));
-            if (DEBUG_LOADERS) {
-                Log.d(TAG, "sort took "
-                        + (SystemClock.uptimeMillis()-sortTime) + "ms");
-            }
-
-            // Create the ApplicationInfos
-            for (int i = 0; i < apps.size(); i++) {
-                ResolveInfo app = apps.get(i);
-                // This builds the icon bitmaps.
-                mBgAllAppsList.add(new AppInfo(packageManager, app,
-                        mIconCache, mLabelCache));
-            }
-
             // Huh? Shouldn't this be inside the Runnable below?
             final ArrayList<AppInfo> added = mBgAllAppsList.added;
             mBgAllAppsList.added = new ArrayList<AppInfo>();
@@ -2522,9 +2923,95 @@
         sWorker.post(task);
     }
 
+    private class AppsAvailabilityCheck extends BroadcastReceiver {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (sBgLock) {
+                final LauncherAppsCompat launcherApps = LauncherAppsCompat
+                        .getInstance(mApp.getContext());
+                ArrayList<String> packagesRemoved;
+                for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {
+                    UserHandleCompat user = entry.getKey();
+                    packagesRemoved = new ArrayList<String>();
+                    for (String pkg : entry.getValue()) {
+                        if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
+                            Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
+                            packagesRemoved.add(pkg);
+                        }
+                    }
+                    if (!packagesRemoved.isEmpty()) {
+                        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,
+                                packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
+                    }
+                }
+                sPendingPackages.clear();
+            }
+        }
+    }
+
+    /**
+     * Workaround to re-check unrestored items, in-case they were installed but the Package-ADD
+     * runnable was missed by the launcher.
+     */
+    public void recheckRestoredItems(final Context context) {
+        Runnable r = new Runnable() {
+
+            @Override
+            public void run() {
+                LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+                HashSet<String> installedPackages = new HashSet<String>();
+                UserHandleCompat user = UserHandleCompat.myUserHandle();
+                synchronized(sBgLock) {
+                    for (ItemInfo info : sBgItemsIdMap.values()) {
+                        if (info instanceof ShortcutInfo) {
+                            ShortcutInfo si = (ShortcutInfo) info;
+                            if (si.isPromise() && si.getTargetComponent() != null
+                                    && launcherApps.isPackageEnabledForProfile(
+                                            si.getTargetComponent().getPackageName(), user)) {
+                                installedPackages.add(si.getTargetComponent().getPackageName());
+                            }
+                        } else if (info instanceof LauncherAppWidgetInfo) {
+                            LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) info;
+                            if (widget.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
+                                    && launcherApps.isPackageEnabledForProfile(
+                                            widget.providerName.getPackageName(), user)) {
+                                installedPackages.add(widget.providerName.getPackageName());
+                            }
+                        }
+                    }
+                }
+
+                if (!installedPackages.isEmpty()) {
+                    final ArrayList<AppInfo> restoredApps = new ArrayList<AppInfo>();
+                    for (String pkg : installedPackages) {
+                        for (LauncherActivityInfoCompat info : launcherApps.getActivityList(pkg, user)) {
+                            restoredApps.add(new AppInfo(context, info, user, mIconCache, null));
+                        }
+                    }
+
+                    final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+                    if (!restoredApps.isEmpty()) {
+                        mHandler.post(new Runnable() {
+                            public void run() {
+                                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                                if (callbacks == cb && cb != null) {
+                                    callbacks.bindAppsRestored(restoredApps);
+                                }
+                            }
+                        });
+                    }
+
+                }
+            }
+        };
+        sWorker.post(r);
+    }
+
     private class PackageUpdatedTask implements Runnable {
         int mOp;
         String[] mPackages;
+        UserHandleCompat mUser;
 
         public static final int OP_NONE = 0;
         public static final int OP_ADD = 1;
@@ -2533,9 +3020,10 @@
         public static final int OP_UNAVAILABLE = 4; // external media unmounted
 
 
-        public PackageUpdatedTask(int op, String[] packages) {
+        public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
             mOp = op;
             mPackages = packages;
+            mUser = user;
         }
 
         public void run() {
@@ -2547,13 +3035,14 @@
                 case OP_ADD:
                     for (int i=0; i<N; i++) {
                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
-                        mBgAllAppsList.addPackage(context, packages[i]);
+                        mIconCache.remove(packages[i], mUser);
+                        mBgAllAppsList.addPackage(context, packages[i], mUser);
                     }
                     break;
                 case OP_UPDATE:
                     for (int i=0; i<N; i++) {
                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
-                        mBgAllAppsList.updatePackage(context, packages[i]);
+                        mBgAllAppsList.updatePackage(context, packages[i], mUser);
                         WidgetPreviewLoader.removePackageFromDb(
                                 mApp.getWidgetPreviewCacheDb(), packages[i]);
                     }
@@ -2562,7 +3051,7 @@
                 case OP_UNAVAILABLE:
                     for (int i=0; i<N; i++) {
                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
-                        mBgAllAppsList.removePackage(packages[i]);
+                        mBgAllAppsList.removePackage(packages[i], mUser);
                         WidgetPreviewLoader.removePackageFromDb(
                                 mApp.getWidgetPreviewCacheDb(), packages[i]);
                     }
@@ -2594,25 +3083,26 @@
 
             if (added != null) {
                 // Ensure that we add all the workspace applications to the db
-                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
-                if (!LauncherAppState.isDisableAllApps()) {
-                    addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added);
-                } else {
+                if (LauncherAppState.isDisableAllApps()) {
                     final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
-                    addAndBindAddedApps(context, addedInfos, cb, added);
+                    addAndBindAddedWorkspaceApps(context, addedInfos);
+                } else {
+                    addAppsToAllApps(context, added);
                 }
             }
+
             if (modified != null) {
                 final ArrayList<AppInfo> modifiedFinal = modified;
 
                 // Update the launcher db to reflect the changes
                 for (AppInfo a : modifiedFinal) {
                     ArrayList<ItemInfo> infos =
-                            getItemInfoForComponentName(a.componentName);
+                            getItemInfoForComponentName(a.componentName, mUser);
                     for (ItemInfo i : infos) {
                         if (isShortcutInfoUpdateable(i)) {
                             ShortcutInfo info = (ShortcutInfo) i;
                             info.title = a.title.toString();
+                            info.contentDescription = a.contentDescription;
                             updateItemInDatabase(context, info);
                         }
                     }
@@ -2637,24 +3127,19 @@
                 // Mark disabled packages in the broadcast to be removed
                 final PackageManager pm = context.getPackageManager();
                 for (int i=0; i<N; i++) {
-                    if (isPackageDisabled(pm, packages[i])) {
+                    if (isPackageDisabled(context, packages[i], mUser)) {
                         removedPackageNames.add(packages[i]);
                     }
                 }
             }
             // Remove all the components associated with this package
             for (String pn : removedPackageNames) {
-                ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn);
-                for (ItemInfo i : infos) {
-                    deleteItemFromDatabase(context, i);
-                }
+                deletePackageFromDatabase(context, pn, mUser);
             }
             // Remove all the specific components
             for (AppInfo a : removedApps) {
-                ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName);
-                for (ItemInfo i : infos) {
-                    deleteItemFromDatabase(context, i);
-                }
+                ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);
+                deleteItemsFromDatabase(context, infos);
             }
             if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {
                 // Remove any queued items from the install queue
@@ -2667,14 +3152,14 @@
                     public void run() {
                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                         if (callbacks == cb && cb != null) {
-                            callbacks.bindComponentsRemoved(removedPackageNames, removedApps);
+                            callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);
                         }
                     }
                 });
             }
 
             final ArrayList<Object> widgetsAndShortcuts =
-                getSortedWidgetsAndShortcuts(context);
+                    getSortedWidgetsAndShortcuts(context);
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -2701,46 +3186,98 @@
     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {
         PackageManager packageManager = context.getPackageManager();
         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
-        widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());
+        widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());
+
         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
-        Collections.sort(widgetsAndShortcuts,
-            new LauncherModel.WidgetAndShortcutNameComparator(packageManager));
+        Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));
         return widgetsAndShortcuts;
     }
 
-    private boolean isPackageDisabled(PackageManager pm, String packageName) {
-        try {
-            PackageInfo pi = pm.getPackageInfo(packageName, 0);
-            return !pi.applicationInfo.enabled;
-        } catch (NameNotFoundException e) {
-            // Fall through
-        }
-        return false;
+    private static boolean isPackageDisabled(Context context, String packageName,
+            UserHandleCompat user) {
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        return !launcherApps.isPackageEnabledForProfile(packageName, user);
     }
-    private boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {
+
+    public static boolean isValidPackageActivity(Context context, ComponentName cn,
+            UserHandleCompat user) {
         if (cn == null) {
             return false;
         }
-        if (isPackageDisabled(pm, cn.getPackageName())) {
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {
             return false;
         }
+        return launcherApps.isActivityEnabledForProfile(cn, user);
+    }
+
+    public static boolean isValidPackage(Context context, String packageName,
+            UserHandleCompat user) {
+        if (packageName == null) {
+            return false;
+        }
+        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+        return launcherApps.isPackageEnabledForProfile(packageName, user);
+    }
+
+    /**
+     * Make an ShortcutInfo object for a restored application or shortcut item that points
+     * to a package that is not yet installed on the system.
+     */
+    public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,
+            int promiseType) {
+        final ShortcutInfo info = new ShortcutInfo();
+        info.user = UserHandleCompat.myUserHandle();
+        mIconCache.getTitleAndIcon(info, intent, info.user, true);
+
+        if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
+            String title = (cursor != null) ? cursor.getString(titleIndex) : null;
+            if (!TextUtils.isEmpty(title)) {
+                info.title = title;
+            }
+            info.status = ShortcutInfo.FLAG_RESTORED_ICON;
+        } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
+            if (TextUtils.isEmpty(info.title)) {
+                info.title = (cursor != null) ? cursor.getString(titleIndex) : "";
+            }
+            info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;
+        } else {
+            throw new InvalidParameterException("Invalid restoreType " + promiseType);
+        }
 
-        try {
-            // Check the activity
-            PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);
-            return (pm.getActivityInfo(cn, 0) != null);
-        } catch (NameNotFoundException e) {
-            return false;
-        }
+        info.contentDescription = mUserManager.getBadgedLabelForUser(
+                info.title.toString(), info.user);
+        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+        info.promisedIntent = intent;
+        return info;
+    }
+
+    /**
+     * Make an Intent object for a restored application or shortcut item that points
+     * to the market page for the item.
+     */
+    private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
+        ComponentName componentName = intent.getComponent();
+        return getMarketIntent(componentName.getPackageName());
+    }
+
+    static Intent getMarketIntent(String packageName) {
+        return new Intent(Intent.ACTION_VIEW)
+            .setData(new Uri.Builder()
+                .scheme("market")
+                .authority("details")
+                .appendQueryParameter("id", packageName)
+                .build());
     }
 
     /**
      * This is called from the code that adds shortcuts from the intent receiver.  This
      * doesn't have a Cursor, but
      */
-    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {
-        return getShortcutInfo(manager, intent, context, null, -1, -1, null);
+    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
+            UserHandleCompat user, Context context) {
+        return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);
     }
 
     /**
@@ -2748,54 +3285,37 @@
      *
      * If c is not null, then it will be used to fill in missing data like the title and icon.
      */
-    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,
-            Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {
-        ComponentName componentName = intent.getComponent();
-        final ShortcutInfo info = new ShortcutInfo();
-        if (componentName != null && !isValidPackageComponent(manager, componentName)) {
-            Log.d(TAG, "Invalid package found in getShortcutInfo: " + componentName);
+    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
+            UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
+            HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {
+        if (user == null) {
+            Log.d(TAG, "Null user found in getShortcutInfo");
             return null;
-        } else {
-            try {
-                PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);
-                info.initFlagsAndFirstInstallTime(pi);
-            } catch (NameNotFoundException e) {
-                Log.d(TAG, "getPackInfo failed for package " +
-                        componentName.getPackageName());
-            }
         }
 
-        // TODO: See if the PackageManager knows about this case.  If it doesn't
-        // then return null & delete this.
+        ComponentName componentName = intent.getComponent();
+        if (componentName == null) {
+            Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);
+            return null;
+        }
+
+        Intent newIntent = new Intent(intent.getAction(), null);
+        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        newIntent.setComponent(componentName);
+        LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);
+        if ((lai == null) && !allowMissingTarget) {
+            Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);
+            return null;
+        }
+
+        final ShortcutInfo info = new ShortcutInfo();
 
         // the resource -- This may implicitly give us back the fallback icon,
         // but don't worry about that.  All we're doing with usingFallbackIcon is
         // to avoid saving lots of copies of that in the database, and most apps
         // have icons anyway.
+        Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);
 
-        // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and
-        // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info
-        // via resolveActivity().
-        Bitmap icon = null;
-        ResolveInfo resolveInfo = null;
-        ComponentName oldComponent = intent.getComponent();
-        Intent newIntent = new Intent(intent.getAction(), null);
-        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-        newIntent.setPackage(oldComponent.getPackageName());
-        List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);
-        for (ResolveInfo i : infos) {
-            ComponentName cn = new ComponentName(i.activityInfo.packageName,
-                    i.activityInfo.name);
-            if (cn.equals(oldComponent)) {
-                resolveInfo = i;
-            }
-        }
-        if (resolveInfo == null) {
-            resolveInfo = manager.resolveActivity(intent, 0);
-        }
-        if (resolveInfo != null) {
-            icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);
-        }
         // the db
         if (icon == null) {
             if (c != null) {
@@ -2804,21 +3324,21 @@
         }
         // the fallback icon
         if (icon == null) {
-            icon = getFallbackIcon();
+            icon = mIconCache.getDefaultIcon(user);
             info.usingFallbackIcon = true;
         }
         info.setIcon(icon);
 
+        // From the cache.
+        if (labelCache != null) {
+            info.title = labelCache.get(componentName);
+        }
+
         // from the resource
-        if (resolveInfo != null) {
-            ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);
-            if (labelCache != null && labelCache.containsKey(key)) {
-                info.title = labelCache.get(key);
-            } else {
-                info.title = resolveInfo.activityInfo.loadLabel(manager);
-                if (labelCache != null) {
-                    labelCache.put(key, info.title);
-                }
+        if (info.title == null && lai != null) {
+            info.title = lai.getLabel();
+            if (labelCache != null) {
+                labelCache.put(componentName, info.title);
             }
         }
         // from the db
@@ -2832,6 +3352,9 @@
             info.title = componentName.getClassName();
         }
         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+        info.user = user;
+        info.contentDescription = mUserManager.getBadgedLabelForUser(
+                info.title.toString(), info.user);
         return info;
     }
 
@@ -2841,14 +3364,14 @@
         for (ItemInfo i : infos) {
             if (i instanceof ShortcutInfo) {
                 ShortcutInfo info = (ShortcutInfo) i;
-                ComponentName cn = info.intent.getComponent();
+                ComponentName cn = info.getTargetComponent();
                 if (cn != null && f.filterItem(null, info, cn)) {
                     filtered.add(info);
                 }
             } else if (i instanceof FolderInfo) {
                 FolderInfo info = (FolderInfo) i;
                 for (ShortcutInfo s : info.contents) {
-                    ComponentName cn = s.intent.getComponent();
+                    ComponentName cn = s.getTargetComponent();
                     if (cn != null && f.filterItem(info, s, cn)) {
                         filtered.add(s);
                     }
@@ -2864,21 +3387,16 @@
         return new ArrayList<ItemInfo>(filtered);
     }
 
-    private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {
+    private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,
+            final UserHandleCompat user) {
         ItemInfoFilter filter  = new ItemInfoFilter() {
             @Override
             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
-                return cn.getPackageName().equals(pn);
-            }
-        };
-        return filterItemInfos(sBgItemsIdMap.values(), filter);
-    }
-
-    private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {
-        ItemInfoFilter filter  = new ItemInfoFilter() {
-            @Override
-            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
-                return cn.equals(cname);
+                if (info.user == null) {
+                    return cn.equals(cname);
+                } else {
+                    return cn.equals(cname) && info.user.equals(user);
+                }
             }
         };
         return filterItemInfos(sBgItemsIdMap.values(), filter);
@@ -2896,6 +3414,10 @@
                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
                 return true;
             }
+            // placeholder shortcuts get special treatment, let them through too.
+            if (info.isPromise()) {
+                return true;
+            }
         }
         return false;
     }
@@ -2909,6 +3431,8 @@
 
         Bitmap icon = null;
         final ShortcutInfo info = new ShortcutInfo();
+        // Non-app shortcuts are only supported for current user.
+        info.user = UserHandleCompat.myUserHandle();
         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
 
         // TODO: If there's an explicit component and we can't install that, delete it.
@@ -2939,14 +3463,14 @@
             }
             // the fallback icon
             if (icon == null) {
-                icon = getFallbackIcon();
+                icon = mIconCache.getDefaultIcon(info.user);
                 info.usingFallbackIcon = true;
             }
             break;
         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
             icon = getIconFromCursor(c, iconIndex, context);
             if (icon == null) {
-                icon = getFallbackIcon();
+                icon = mIconCache.getDefaultIcon(info.user);
                 info.customIcon = false;
                 info.usingFallbackIcon = true;
             } else {
@@ -2954,7 +3478,7 @@
             }
             break;
         default:
-            icon = getFallbackIcon();
+            icon = mIconCache.getDefaultIcon(info.user);
             info.usingFallbackIcon = true;
             info.customIcon = false;
             break;
@@ -2993,7 +3517,7 @@
     /**
      * Attempts to find an AppWidgetProviderInfo that matches the given component.
      */
-    AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,
+    static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,
             ComponentName component) {
         List<AppWidgetProviderInfo> widgets =
             AppWidgetManager.getInstance(context).getInstalledProviders();
@@ -3005,44 +3529,6 @@
         return null;
     }
 
-    /**
-     * Returns a list of all the widgets that can handle configuration with a particular mimeType.
-     */
-    List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {
-        final PackageManager packageManager = context.getPackageManager();
-        final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =
-            new ArrayList<WidgetMimeTypeHandlerData>();
-
-        final Intent supportsIntent =
-            new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);
-        supportsIntent.setType(mimeType);
-
-        // Create a set of widget configuration components that we can test against
-        final List<AppWidgetProviderInfo> widgets =
-            AppWidgetManager.getInstance(context).getInstalledProviders();
-        final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =
-            new HashMap<ComponentName, AppWidgetProviderInfo>();
-        for (AppWidgetProviderInfo info : widgets) {
-            configurationComponentToWidget.put(info.configure, info);
-        }
-
-        // Run through each of the intents that can handle this type of clip data, and cross
-        // reference them with the components that are actual configuration components
-        final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,
-                PackageManager.MATCH_DEFAULT_ONLY);
-        for (ResolveInfo info : activities) {
-            final ActivityInfo activityInfo = info.activityInfo;
-            final ComponentName infoComponent = new ComponentName(activityInfo.packageName,
-                    activityInfo.name);
-            if (configurationComponentToWidget.containsKey(infoComponent)) {
-                supportedConfigurationActivities.add(
-                        new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,
-                                configurationComponentToWidget.get(infoComponent)));
-            }
-        }
-        return supportedConfigurationActivities;
-    }
-
     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {
         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
@@ -3071,7 +3557,8 @@
                             iconResource.packageName);
                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);
                     icon = Utilities.createIconBitmap(
-                            mIconCache.getFullResIcon(resources, id), context);
+                            mIconCache.getFullResIcon(resources, id),
+                            context);
                 } catch (Exception e) {
                     Log.w(TAG, "Could not load shortcut icon: " + extra);
                 }
@@ -3080,17 +3567,22 @@
 
         final ShortcutInfo info = new ShortcutInfo();
 
+        // Only support intents for current user for now. Intents sent from other
+        // users wouldn't get here without intent forwarding anyway.
+        info.user = UserHandleCompat.myUserHandle();
         if (icon == null) {
             if (fallbackIcon != null) {
                 icon = fallbackIcon;
             } else {
-                icon = getFallbackIcon();
+                icon = mIconCache.getDefaultIcon(info.user);
                 info.usingFallbackIcon = true;
             }
         }
         info.setIcon(icon);
 
         info.title = name;
+        info.contentDescription = mUserManager.getBadgedLabelForUser(
+                info.title.toString(), info.user);
         info.intent = intent;
         info.customIcon = customIcon;
         info.iconResource = iconResource;
@@ -3156,12 +3648,18 @@
         final Collator collator = Collator.getInstance();
         return new Comparator<AppInfo>() {
             public final int compare(AppInfo a, AppInfo b) {
-                int result = collator.compare(a.title.toString().trim(),
-                        b.title.toString().trim());
-                if (result == 0) {
-                    result = a.componentName.compareTo(b.componentName);
+                if (a.user.equals(b.user)) {
+                    int result = collator.compare(a.title.toString().trim(),
+                            b.title.toString().trim());
+                    if (result == 0) {
+                        result = a.componentName.compareTo(b.componentName);
+                    }
+                    return result;
+                } else {
+                    // TODO Need to figure out rules for sorting
+                    // profiles, this puts work second.
+                    return a.user.toString().compareTo(b.user.toString());
                 }
-                return result;
             }
         };
     }
@@ -3173,14 +3671,6 @@
             return 0;
         }
     };
-    public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {
-        final Collator collator = Collator.getInstance();
-        return new Comparator<AppWidgetProviderInfo>() {
-            public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
-                return collator.compare(a.label.toString().trim(), b.label.toString().trim());
-            }
-        };
-    }
     static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {
         if (info.activityInfo != null) {
             return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
@@ -3188,35 +3678,32 @@
             return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
         }
     }
-    public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
+    public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {
         private Collator mCollator;
-        private PackageManager mPackageManager;
         private HashMap<Object, CharSequence> mLabelCache;
         ShortcutNameComparator(PackageManager pm) {
-            mPackageManager = pm;
             mLabelCache = new HashMap<Object, CharSequence>();
             mCollator = Collator.getInstance();
         }
-        ShortcutNameComparator(PackageManager pm, HashMap<Object, CharSequence> labelCache) {
-            mPackageManager = pm;
+        ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {
             mLabelCache = labelCache;
             mCollator = Collator.getInstance();
         }
-        public final int compare(ResolveInfo a, ResolveInfo b) {
-            CharSequence labelA, labelB;
-            ComponentName keyA = LauncherModel.getComponentNameFromResolveInfo(a);
-            ComponentName keyB = LauncherModel.getComponentNameFromResolveInfo(b);
+        public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {
+            String labelA, labelB;
+            ComponentName keyA = a.getComponentName();
+            ComponentName keyB = b.getComponentName();
             if (mLabelCache.containsKey(keyA)) {
-                labelA = mLabelCache.get(keyA);
+                labelA = mLabelCache.get(keyA).toString();
             } else {
-                labelA = a.loadLabel(mPackageManager).toString().trim();
+                labelA = a.getLabel().toString().trim();
 
                 mLabelCache.put(keyA, labelA);
             }
             if (mLabelCache.containsKey(keyB)) {
-                labelB = mLabelCache.get(keyB);
+                labelB = mLabelCache.get(keyB).toString();
             } else {
-                labelB = b.loadLabel(mPackageManager).toString().trim();
+                labelB = b.getLabel().toString().trim();
 
                 mLabelCache.put(keyB, labelB);
             }
@@ -3224,11 +3711,14 @@
         }
     };
     public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
-        private Collator mCollator;
-        private PackageManager mPackageManager;
-        private HashMap<Object, String> mLabelCache;
-        WidgetAndShortcutNameComparator(PackageManager pm) {
-            mPackageManager = pm;
+        private final AppWidgetManagerCompat mManager;
+        private final PackageManager mPackageManager;
+        private final HashMap<Object, String> mLabelCache;
+        private final Collator mCollator;
+
+        WidgetAndShortcutNameComparator(Context context) {
+            mManager = AppWidgetManagerCompat.getInstance(context);
+            mPackageManager = context.getPackageManager();
             mLabelCache = new HashMap<Object, String>();
             mCollator = Collator.getInstance();
         }
@@ -3237,23 +3727,28 @@
             if (mLabelCache.containsKey(a)) {
                 labelA = mLabelCache.get(a);
             } else {
-                labelA = (a instanceof AppWidgetProviderInfo) ?
-                    ((AppWidgetProviderInfo) a).label :
-                    ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();
+                labelA = (a instanceof AppWidgetProviderInfo)
+                        ? mManager.loadLabel((AppWidgetProviderInfo) a)
+                        : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();
                 mLabelCache.put(a, labelA);
             }
             if (mLabelCache.containsKey(b)) {
                 labelB = mLabelCache.get(b);
             } else {
-                labelB = (b instanceof AppWidgetProviderInfo) ?
-                    ((AppWidgetProviderInfo) b).label :
-                    ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();
+                labelB = (b instanceof AppWidgetProviderInfo)
+                        ? mManager.loadLabel((AppWidgetProviderInfo) b)
+                        : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();
                 mLabelCache.put(b, labelB);
             }
             return mCollator.compare(labelA, labelB);
         }
     };
 
+    static boolean isValidProvider(AppWidgetProviderInfo provider) {
+        return (provider != null) && (provider.provider != null)
+                && (provider.provider.getPackageName() != null);
+    }
+
     public void dumpState() {
         Log.d(TAG, "mCallbacks=" + mCallbacks);
         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);
diff --git a/src/com/android/launcher3/LauncherPreferencesBackupHelper.java b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java
new file mode 100644
index 0000000..6f9c05c
--- /dev/null
+++ b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.app.backup.BackupDataInputStream;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.util.Log;
+
+public class LauncherPreferencesBackupHelper extends SharedPreferencesBackupHelper {
+
+    private static final String TAG = "LauncherPreferencesBackupHelper";
+    private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
+
+    private final boolean mRestoreEnabled;
+
+    public LauncherPreferencesBackupHelper(Context context,  String sharedPreferencesKey,
+            boolean restoreEnabled) {
+        super(context, sharedPreferencesKey);
+        mRestoreEnabled = restoreEnabled;
+    }
+
+    @Override
+    public void restoreEntity(BackupDataInputStream data) {
+        if (mRestoreEnabled) {
+            if (VERBOSE) Log.v(TAG, "restoring preferences");
+            super.restoreEntity(data);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 7adbade..6cc1688 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -22,16 +22,20 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.ContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.OperationApplicationException;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.database.Cursor;
 import android.database.SQLException;
@@ -45,11 +49,13 @@
 import android.os.Bundle;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Xml;
+import android.util.SparseArray;
 
+import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
 import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
 import com.android.launcher3.config.ProviderConfig;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -59,6 +65,7 @@
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
@@ -68,7 +75,7 @@
 
     private static final String DATABASE_NAME = "launcher.db";
 
-    private static final int DATABASE_VERSION = 15;
+    private static final int DATABASE_VERSION = 20;
 
     static final String OLD_AUTHORITY = "com.android.launcher2.settings";
     static final String AUTHORITY = ProviderConfig.AUTHORITY;
@@ -83,12 +90,14 @@
             "UPGRADED_FROM_OLD_DATABASE";
     static final String EMPTY_DATABASE_CREATED =
             "EMPTY_DATABASE_CREATED";
-    static final String DEFAULT_WORKSPACE_RESOURCE_ID =
-            "DEFAULT_WORKSPACE_RESOURCE_ID";
 
     private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
             "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
 
+    private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
+
+    private LauncherProviderChangeListener mListener;
+
     /**
      * {@link Uri} triggered at any registered {@link android.database.ContentObserver} when
      * {@link AppWidgetHost#deleteHost()} is called during database creation.
@@ -108,6 +117,14 @@
         return true;
     }
 
+    public boolean wasNewDbCreated() {
+        return mOpenHelper.wasNewDbCreated();
+    }
+
+    public void setLauncherProviderChangeListener(LauncherProviderChangeListener listener) {
+        mListener = listener;
+    }
+
     @Override
     public String getType(Uri uri) {
         SqlArguments args = new SqlArguments(uri, null, null);
@@ -138,9 +155,10 @@
         if (values == null) {
             throw new RuntimeException("Error: attempting to insert null values");
         }
-        if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+        if (!values.containsKey(LauncherSettings.ChangeLogColumns._ID)) {
             throw new RuntimeException("Error: attempting to add item without specifying an id");
         }
+        helper.checkId(table, values);
         return db.insert(table, nullColumnHack, values);
     }
 
@@ -154,6 +172,14 @@
     public Uri insert(Uri uri, ContentValues initialValues) {
         SqlArguments args = new SqlArguments(uri);
 
+        // In very limited cases, we support system|signature permission apps to add to the db
+        String externalAdd = uri.getQueryParameter(URI_PARAM_IS_EXTERNAL_ADD);
+        if (externalAdd != null && "true".equals(externalAdd)) {
+            if (!mOpenHelper.initializeExternalAdd(initialValues)) {
+                return null;
+            }
+        }
+
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         addModifiedTime(initialValues);
         final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
@@ -165,6 +191,7 @@
         return uri;
     }
 
+
     @Override
     public int bulkInsert(Uri uri, ContentValues[] values) {
         SqlArguments args = new SqlArguments(uri);
@@ -189,6 +216,20 @@
     }
 
     @Override
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+            throws OperationApplicationException {
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            ContentProviderResult[] result =  super.applyBatch(operations);
+            db.setTransactionSuccessful();
+            return result;
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
         SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
 
@@ -219,6 +260,9 @@
 
         // always notify the backup agent
         LauncherBackupAgentHelper.dataChanged(getContext());
+        if (mListener != null) {
+            mListener.onLauncherProviderChange();
+        }
     }
 
     private void addModifiedTime(ContentValues values) {
@@ -264,44 +308,64 @@
     }
 
     /**
-     * @param workspaceResId that can be 0 to use default or non-zero for specific resource
+     * Clears all the data for a fresh start.
      */
-    synchronized public void loadDefaultFavoritesIfNecessary(int origWorkspaceResId) {
+    synchronized public void createEmptyDB() {
+        mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
+    }
+
+    /**
+     * Loads the default workspace based on the following priority scheme:
+     *   1) From a package provided by play store
+     *   2) From a partner configuration APK, already in the system image
+     *   3) The default configuration for the particular device
+     */
+    synchronized public void loadDefaultFavoritesIfNecessary() {
         String spKey = LauncherAppState.getSharedPreferencesKey();
         SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
 
         if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
-            int workspaceResId = origWorkspaceResId;
+            Log.d(TAG, "loading default workspace");
 
-            // Use default workspace resource if none provided
-            if (workspaceResId == 0) {
-                workspaceResId =
-                        sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, getDefaultWorkspaceResourceId());
+            WorkspaceLoader loader = AutoInstallsLayout.get(getContext(),
+                    mOpenHelper.mAppWidgetHost, mOpenHelper);
+
+            if (loader == null) {
+                final Partner partner = Partner.get(getContext().getPackageManager());
+                if (partner != null && partner.hasDefaultLayout()) {
+                    final Resources partnerRes = partner.getResources();
+                    int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
+                            "xml", partner.getPackageName());
+                    if (workspaceResId != 0) {
+                        loader = new SimpleWorkspaceLoader(mOpenHelper, partnerRes, workspaceResId);
+                    }
+                }
+            }
+
+            if (loader == null) {
+                loader = new SimpleWorkspaceLoader(mOpenHelper, getContext().getResources(),
+                        getDefaultWorkspaceResourceId());
             }
 
             // Populate favorites table with initial favorites
-            SharedPreferences.Editor editor = sp.edit();
-            editor.remove(EMPTY_DATABASE_CREATED);
-            if (origWorkspaceResId != 0) {
-                editor.putInt(DEFAULT_WORKSPACE_RESOURCE_ID, origWorkspaceResId);
-            }
-
-            mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), workspaceResId);
-            mOpenHelper.setFlagJustLoadedOldDb();
+            SharedPreferences.Editor editor = sp.edit().remove(EMPTY_DATABASE_CREATED);
+            mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), loader);
             editor.commit();
         }
     }
 
     public void migrateLauncher2Shortcuts() {
         mOpenHelper.migrateLauncher2Shortcuts(mOpenHelper.getWritableDatabase(),
-                LauncherSettings.Favorites.OLD_CONTENT_URI);
+                Uri.parse(getContext().getString(R.string.old_launcher_provider_uri)));
     }
 
     private static int getDefaultWorkspaceResourceId() {
+        LauncherAppState app = LauncherAppState.getInstance();
+        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
         if (LauncherAppState.isDisableAllApps()) {
-            return R.xml.default_workspace_no_all_apps;
+            return grid.defaultNoAllAppsLayoutId;
         } else {
-            return R.xml.default_workspace;
+            return grid.defaultLayoutId;
         }
     }
 
@@ -319,31 +383,57 @@
     public void deleteDatabase() {
         // Are you sure? (y/n)
         final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        final String dbFile = db.getPath();
+        final File dbFile = new File(db.getPath());
         mOpenHelper.close();
-        SQLiteDatabase.deleteDatabase(new File(dbFile));
+        if (dbFile.exists()) {
+            SQLiteDatabase.deleteDatabase(dbFile);
+        }
         mOpenHelper = new DatabaseHelper(getContext());
     }
 
-    private static class DatabaseHelper extends SQLiteOpenHelper {
+    private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
+        private static final String TAG_RESOLVE = "resolve";
         private static final String TAG_FAVORITES = "favorites";
         private static final String TAG_FAVORITE = "favorite";
-        private static final String TAG_CLOCK = "clock";
-        private static final String TAG_SEARCH = "search";
         private static final String TAG_APPWIDGET = "appwidget";
         private static final String TAG_SHORTCUT = "shortcut";
         private static final String TAG_FOLDER = "folder";
+        private static final String TAG_PARTNER_FOLDER = "partner-folder";
         private static final String TAG_EXTRA = "extra";
         private static final String TAG_INCLUDE = "include";
 
+        // Style attrs -- "Favorite"
+        private static final String ATTR_CLASS_NAME = "className";
+        private static final String ATTR_PACKAGE_NAME = "packageName";
+        private static final String ATTR_CONTAINER = "container";
+        private static final String ATTR_SCREEN = "screen";
+        private static final String ATTR_X = "x";
+        private static final String ATTR_Y = "y";
+        private static final String ATTR_SPAN_X = "spanX";
+        private static final String ATTR_SPAN_Y = "spanY";
+        private static final String ATTR_ICON = "icon";
+        private static final String ATTR_TITLE = "title";
+        private static final String ATTR_URI = "uri";
+
+        // Style attrs -- "Include"
+        private static final String ATTR_WORKSPACE = "workspace";
+
+        // Style attrs -- "Extra"
+        private static final String ATTR_KEY = "key";
+        private static final String ATTR_VALUE = "value";
+
         private final Context mContext;
+        private final PackageManager mPackageManager;
         private final AppWidgetHost mAppWidgetHost;
         private long mMaxItemId = -1;
         private long mMaxScreenId = -1;
 
+        private boolean mNewDbCreated = false;
+
         DatabaseHelper(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
             mContext = context;
+            mPackageManager = context.getPackageManager();
             mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
 
             // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
@@ -356,6 +446,10 @@
             }
         }
 
+        public boolean wasNewDbCreated() {
+            return mNewDbCreated;
+        }
+
         /**
          * Send notification that we've deleted the {@link AppWidgetHost},
          * probably as part of the initial database creation. The receiver may
@@ -373,6 +467,11 @@
 
             mMaxItemId = 1;
             mMaxScreenId = 0;
+            mNewDbCreated = true;
+
+            UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+            long userSerialNumber = userManager.getSerialNumberForUser(
+                    UserHandleCompat.myUserHandle());
 
             db.execSQL("CREATE TABLE favorites (" +
                     "_id INTEGER PRIMARY KEY," +
@@ -394,7 +493,9 @@
                     "uri TEXT," +
                     "displayMode INTEGER," +
                     "appWidgetProvider TEXT," +
-                    "modified INTEGER NOT NULL DEFAULT 0" +
+                    "modified INTEGER NOT NULL DEFAULT 0," +
+                    "restored INTEGER NOT NULL DEFAULT 0," +
+                    "profileId INTEGER DEFAULT " + userSerialNumber +
                     ");");
             addWorkspacesTable(db);
 
@@ -420,7 +521,7 @@
                         "/old_favorites?notify=true");
                 if (!convertDatabase(db, uri, permuteScreensCb, true)) {
                     // Try and upgrade from the Launcher2 db
-                    uri = LauncherSettings.Favorites.OLD_CONTENT_URI;
+                    uri = Uri.parse(mContext.getString(R.string.old_launcher_provider_uri));
                     if (!convertDatabase(db, uri, permuteScreensCb, false)) {
                         // If we fail, then set a flag to load the default workspace
                         setFlagEmptyDbCreated();
@@ -446,6 +547,37 @@
                     ");");
         }
 
+        private void removeOrphanedItems(SQLiteDatabase db) {
+            // Delete items directly on the workspace who's screen id doesn't exist
+            //  "DELETE FROM favorites WHERE screen NOT IN (SELECT _id FROM workspaceScreens)
+            //   AND container = -100"
+            String removeOrphanedDesktopItems = "DELETE FROM " + TABLE_FAVORITES +
+                    " WHERE " +
+                    LauncherSettings.Favorites.SCREEN + " NOT IN (SELECT " +
+                    LauncherSettings.WorkspaceScreens._ID + " FROM " + TABLE_WORKSPACE_SCREENS + ")" +
+                    " AND " +
+                    LauncherSettings.Favorites.CONTAINER + " = " +
+                    LauncherSettings.Favorites.CONTAINER_DESKTOP;
+            db.execSQL(removeOrphanedDesktopItems);
+
+            // Delete items contained in folders which no longer exist (after above statement)
+            //  "DELETE FROM favorites  WHERE container <> -100 AND container <> -101 AND container
+            //   NOT IN (SELECT _id FROM favorites WHERE itemType = 2)"
+            String removeOrphanedFolderItems = "DELETE FROM " + TABLE_FAVORITES +
+                    " WHERE " +
+                    LauncherSettings.Favorites.CONTAINER + " <> " +
+                    LauncherSettings.Favorites.CONTAINER_DESKTOP +
+                    " AND "
+                    + LauncherSettings.Favorites.CONTAINER + " <> " +
+                    LauncherSettings.Favorites.CONTAINER_HOTSEAT +
+                    " AND "
+                    + LauncherSettings.Favorites.CONTAINER + " NOT IN (SELECT " +
+                    LauncherSettings.Favorites._ID + " FROM " + TABLE_FAVORITES +
+                    " WHERE " + LauncherSettings.Favorites.ITEM_TYPE + " = " +
+                    LauncherSettings.Favorites.ITEM_TYPE_FOLDER + ")";
+            db.execSQL(removeOrphanedFolderItems);
+        }
+
         private void setFlagJustLoadedOldDb() {
             String spKey = LauncherAppState.getSharedPreferencesKey();
             SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
@@ -657,7 +789,8 @@
                 }
 
                 // Add default hotseat icons
-                loadFavorites(db, R.xml.update_workspace);
+                loadFavorites(db, new SimpleWorkspaceLoader(this, mContext.getResources(),
+                        R.xml.update_workspace));
                 version = 9;
             }
 
@@ -701,7 +834,6 @@
                 }
             }
 
-
             if (version < 15) {
                 db.beginTransaction();
                 try {
@@ -720,6 +852,55 @@
                 }
             }
 
+
+            if (version < 16) {
+                db.beginTransaction();
+                try {
+                    // Insert new column for holding restore status
+                    db.execSQL("ALTER TABLE favorites " +
+                            "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;");
+                    db.setTransactionSuccessful();
+                    version = 16;
+                } catch (SQLException ex) {
+                    // Old version remains, which means we wipe old data
+                    Log.e(TAG, ex.getMessage(), ex);
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
+            if (version < 17) {
+                // We use the db version upgrade here to identify users who may not have seen
+                // clings yet (because they weren't available), but for whom the clings are now
+                // available (tablet users). Because one of the possible cling flows (migration)
+                // is very destructive (wipes out workspaces), we want to prevent this from showing
+                // until clear data. We do so by marking that the clings have been shown.
+                LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext);
+                version = 17;
+            }
+
+            if (version < 18) {
+                // No-op
+                version = 18;
+            }
+
+            if (version < 19) {
+                // Due to a data loss bug, some users may have items associated with screen ids
+                // which no longer exist. Since this can cause other problems, and since the user
+                // will never see these items anyway, we use database upgrade as an opportunity to
+                // clean things up.
+                removeOrphanedItems(db);
+                version = 19;
+            }
+
+            if (version < 20) {
+                // Add userId column
+                if (addProfileColumn(db)) {
+                    version = 20;
+                }
+                // else old version remains, which means we wipe old data
+            }
+
             if (version != DATABASE_VERSION) {
                 Log.w(TAG, "Destroying all old data.");
                 db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -729,6 +910,47 @@
             }
         }
 
+        @Override
+        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            // This shouldn't happen -- throw our hands up in the air and start over.
+            Log.w(TAG, "Database version downgrade from: " + oldVersion + " to " + newVersion +
+                    ". Wiping databse.");
+            createEmptyDB(db);
+        }
+
+
+        /**
+         * Clears all the data for a fresh start.
+         */
+        public void createEmptyDB(SQLiteDatabase db) {
+            db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
+            db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKSPACE_SCREENS);
+            onCreate(db);
+        }
+
+        private boolean addProfileColumn(SQLiteDatabase db) {
+            db.beginTransaction();
+            try {
+                UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+                // Default to the serial number of this user, for older
+                // shortcuts.
+                long userSerialNumber = userManager.getSerialNumberForUser(
+                        UserHandleCompat.myUserHandle());
+                // Insert new column for holding user serial number
+                db.execSQL("ALTER TABLE favorites " +
+                        "ADD COLUMN profileId INTEGER DEFAULT "
+                                        + userSerialNumber + ";");
+                db.setTransactionSuccessful();
+            } catch (SQLException ex) {
+                // Old version remains, which means we wipe old data
+                Log.e(TAG, ex.getMessage(), ex);
+                return false;
+            } finally {
+                db.endTransaction();
+            }
+            return true;
+        }
+
         private boolean updateContactsShortcuts(SQLiteDatabase db) {
             final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE,
                     new int[] { Favorites.ITEM_TYPE_SHORTCUT });
@@ -870,6 +1092,7 @@
         // constructor from the worker thread; however, this doesn't extend until after the
         // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
         // after that point
+        @Override
         public long generateNewItemId() {
             if (mMaxItemId < 0) {
                 throw new RuntimeException("Error: max item id was not initialized");
@@ -878,10 +1101,24 @@
             return mMaxItemId;
         }
 
+        @Override
+        public long insertAndCheck(SQLiteDatabase db, ContentValues values) {
+            return dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
+        }
+
         public void updateMaxItemId(long id) {
             mMaxItemId = id + 1;
         }
 
+        public void checkId(String table, ContentValues values) {
+            long id = values.getAsLong(LauncherSettings.BaseLauncherColumns._ID);
+            if (table == LauncherProvider.TABLE_WORKSPACE_SCREENS) {
+                mMaxScreenId = Math.max(id, mMaxScreenId);
+            }  else {
+                mMaxItemId = Math.max(id, mMaxItemId);
+            }
+        }
+
         private long initializeMaxItemId(SQLiteDatabase db) {
             Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
 
@@ -1033,6 +1270,93 @@
             if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId);
         }
 
+        private boolean initializeExternalAdd(ContentValues values) {
+            // 1. Ensure that externally added items have a valid item id
+            long id = generateNewItemId();
+            values.put(LauncherSettings.Favorites._ID, id);
+
+            // 2. In the case of an app widget, and if no app widget id is specified, we
+            // attempt allocate and bind the widget.
+            Integer itemType = values.getAsInteger(LauncherSettings.Favorites.ITEM_TYPE);
+            if (itemType != null &&
+                    itemType.intValue() == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
+                    !values.containsKey(LauncherSettings.Favorites.APPWIDGET_ID)) {
+
+                final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+                ComponentName cn = ComponentName.unflattenFromString(
+                        values.getAsString(Favorites.APPWIDGET_PROVIDER));
+
+                if (cn != null) {
+                    try {
+                        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+                        values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
+                        if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,cn)) {
+                            return false;
+                        }
+                    } catch (RuntimeException e) {
+                        Log.e(TAG, "Failed to initialize external widget", e);
+                        return false;
+                    }
+                } else {
+                    return false;
+                }
+            }
+
+            // Add screen id if not present
+            long screenId = values.getAsLong(LauncherSettings.Favorites.SCREEN);
+            if (!addScreenIdIfNecessary(screenId)) {
+                return false;
+            }
+            return true;
+        }
+
+        // Returns true of screen id exists, or if successfully added
+        private boolean addScreenIdIfNecessary(long screenId) {
+            if (!hasScreenId(screenId)) {
+                int rank = getMaxScreenRank() + 1;
+
+                ContentValues v = new ContentValues();
+                v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
+                v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, rank);
+                if (dbInsertAndCheck(this, getWritableDatabase(),
+                        TABLE_WORKSPACE_SCREENS, null, v) < 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private boolean hasScreenId(long screenId) {
+            SQLiteDatabase db = getWritableDatabase();
+            Cursor c = db.rawQuery("SELECT * FROM " + TABLE_WORKSPACE_SCREENS + " WHERE "
+                    + LauncherSettings.WorkspaceScreens._ID + " = " + screenId, null);
+            if (c != null) {
+                int count = c.getCount();
+                c.close();
+                return count > 0;
+            } else {
+                return false;
+            }
+        }
+
+        private int getMaxScreenRank() {
+            SQLiteDatabase db = getWritableDatabase();
+            Cursor c = db.rawQuery("SELECT MAX(" + LauncherSettings.WorkspaceScreens.SCREEN_RANK
+                    + ") FROM " + TABLE_WORKSPACE_SCREENS, null);
+
+            // get the result
+            final int maxRankIndex = 0;
+            int rank = -1;
+            if (c != null && c.moveToNext()) {
+                rank = c.getInt(maxRankIndex);
+            }
+            if (c != null) {
+                c.close();
+            }
+
+            return rank;
+        }
+
         private static final void beginDocument(XmlPullParser parser, String firstElementName)
                 throws XmlPullParserException, IOException {
             int type;
@@ -1051,24 +1375,55 @@
             }
         }
 
+        private static Intent buildMainIntent() {
+            Intent intent = new Intent(Intent.ACTION_MAIN, null);
+            intent.addCategory(Intent.CATEGORY_LAUNCHER);
+            return intent;
+        }
+
+        private int loadFavorites(SQLiteDatabase db, WorkspaceLoader loader) {
+            ArrayList<Long> screenIds = new ArrayList<Long>();
+            // TODO: Use multiple loaders with fall-back and transaction.
+            int count = loader.loadLayout(db, screenIds);
+
+            // Add the screens specified by the items above
+            Collections.sort(screenIds);
+            int rank = 0;
+            ContentValues values = new ContentValues();
+            for (Long id : screenIds) {
+                values.clear();
+                values.put(LauncherSettings.WorkspaceScreens._ID, id);
+                values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, rank);
+                if (dbInsertAndCheck(this, db, TABLE_WORKSPACE_SCREENS, null, values) < 0) {
+                    throw new RuntimeException("Failed initialize screen table"
+                            + "from default layout");
+                }
+                rank++;
+            }
+
+            // Ensure that the max ids are initialized
+            mMaxItemId = initializeMaxItemId(db);
+            mMaxScreenId = initializeMaxScreenId(db);
+
+            return count;
+        }
+
         /**
          * Loads the default set of favorite packages from an xml file.
          *
          * @param db The database to write the values into
          * @param filterContainerId The specific container id of items to load
+         * @param the set of screenIds which are used by the favorites
          */
-        private int loadFavorites(SQLiteDatabase db, int workspaceResourceId) {
-            Intent intent = new Intent(Intent.ACTION_MAIN, null);
-            intent.addCategory(Intent.CATEGORY_LAUNCHER);
-            ContentValues values = new ContentValues();
+        private int loadFavoritesRecursive(SQLiteDatabase db, Resources res, int workspaceResourceId,
+                ArrayList<Long> screenIds) {
 
+            ContentValues values = new ContentValues();
             if (LOGD) Log.v(TAG, String.format("Loading favorites from resid=0x%08x", workspaceResourceId));
 
-            PackageManager packageManager = mContext.getPackageManager();
-            int i = 0;
+            int count = 0;
             try {
-                XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId);
-                AttributeSet attrs = Xml.asAttributeSet(parser);
+                XmlResourceParser parser = res.getXml(workspaceResourceId);
                 beginDocument(parser, TAG_FAVORITES);
 
                 final int depth = parser.getDepth();
@@ -1085,38 +1440,34 @@
                     final String name = parser.getName();
 
                     if (TAG_INCLUDE.equals(name)) {
-                        final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Include);
 
-                        final int resId = a.getResourceId(R.styleable.Include_workspace, 0);
+                        final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
 
                         if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s<include workspace=%08x>"),
                                 "", resId));
 
                         if (resId != 0 && resId != workspaceResourceId) {
                             // recursively load some more favorites, why not?
-                            i += loadFavorites(db, resId);
+                            count += loadFavoritesRecursive(db, res, resId, screenIds);
                             added = false;
                         } else {
                             Log.w(TAG, String.format("Skipping <include workspace=0x%08x>", resId));
                         }
 
-                        a.recycle();
-
                         if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s</include>"), ""));
                         continue;
                     }
 
                     // Assuming it's a <favorite> at this point
-                    TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
-
                     long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
-                    if (a.hasValue(R.styleable.Favorite_container)) {
-                        container = Long.valueOf(a.getString(R.styleable.Favorite_container));
+                    String strContainer = getAttributeValue(parser, ATTR_CONTAINER);
+                    if (strContainer != null) {
+                        container = Long.valueOf(strContainer);
                     }
 
-                    String screen = a.getString(R.styleable.Favorite_screen);
-                    String x = a.getString(R.styleable.Favorite_x);
-                    String y = a.getString(R.styleable.Favorite_y);
+                    String screen = getAttributeValue(parser, ATTR_SCREEN);
+                    String x = getAttributeValue(parser, ATTR_X);
+                    String y = getAttributeValue(parser, ATTR_Y);
 
                     values.clear();
                     values.put(LauncherSettings.Favorites.CONTAINER, container);
@@ -1125,8 +1476,8 @@
                     values.put(LauncherSettings.Favorites.CELLY, y);
 
                     if (LOGD) {
-                        final String title = a.getString(R.styleable.Favorite_title);
-                        final String pkg = a.getString(R.styleable.Favorite_packageName);
+                        final String title = getAttributeValue(parser, ATTR_TITLE);
+                        final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
                         final String something = title != null ? title : pkg;
                         Log.v(TAG, String.format(
                                 ("%" + (2*(depth+1)) + "s<%s%s c=%d s=%s x=%s y=%s>"),
@@ -1136,82 +1487,62 @@
                     }
 
                     if (TAG_FAVORITE.equals(name)) {
-                        long id = addAppShortcut(db, values, a, packageManager, intent);
+                        long id = addAppShortcut(db, values, parser);
                         added = id >= 0;
-                    } else if (TAG_SEARCH.equals(name)) {
-                        added = addSearchWidget(db, values);
-                    } else if (TAG_CLOCK.equals(name)) {
-                        added = addClockWidget(db, values);
                     } else if (TAG_APPWIDGET.equals(name)) {
-                        added = addAppWidget(parser, attrs, type, db, values, a, packageManager);
+                        added = addAppWidget(parser, type, db, values);
                     } else if (TAG_SHORTCUT.equals(name)) {
-                        long id = addUriShortcut(db, values, a);
+                        long id = addUriShortcut(db, values, res, parser);
                         added = id >= 0;
-                    } else if (TAG_FOLDER.equals(name)) {
-                        String title;
-                        int titleResId =  a.getResourceId(R.styleable.Favorite_title, -1);
-                        if (titleResId != -1) {
-                            title = mContext.getResources().getString(titleResId);
-                        } else {
-                            title = mContext.getResources().getString(R.string.folder_name);
-                        }
-                        values.put(LauncherSettings.Favorites.TITLE, title);
-                        long folderId = addFolder(db, values);
-                        added = folderId >= 0;
-
-                        ArrayList<Long> folderItems = new ArrayList<Long>();
-
-                        int folderDepth = parser.getDepth();
+                    } else if (TAG_RESOLVE.equals(name)) {
+                        // This looks through the contained favorites (or meta-favorites) and
+                        // attempts to add them as shortcuts in the fallback group's location
+                        // until one is added successfully.
+                        added = false;
+                        final int groupDepth = parser.getDepth();
                         while ((type = parser.next()) != XmlPullParser.END_TAG ||
-                                parser.getDepth() > folderDepth) {
+                                parser.getDepth() > groupDepth) {
                             if (type != XmlPullParser.START_TAG) {
                                 continue;
                             }
-                            final String folder_item_name = parser.getName();
-
-                            TypedArray ar = mContext.obtainStyledAttributes(attrs,
-                                    R.styleable.Favorite);
-                            values.clear();
-                            values.put(LauncherSettings.Favorites.CONTAINER, folderId);
-
-                            if (LOGD) {
-                                final String pkg = ar.getString(R.styleable.Favorite_packageName);
-                                final String uri = ar.getString(R.styleable.Favorite_uri);
-                                Log.v(TAG, String.format(("%" + (2*(folderDepth+1)) + "s<%s \"%s\">"), "",
-                                        folder_item_name, uri != null ? uri : pkg));
-                            }
-
-                            if (TAG_FAVORITE.equals(folder_item_name) && folderId >= 0) {
-                                long id =
-                                    addAppShortcut(db, values, ar, packageManager, intent);
-                                if (id >= 0) {
-                                    folderItems.add(id);
+                            final String fallback_item_name = parser.getName();
+                            if (!added) {
+                                if (TAG_FAVORITE.equals(fallback_item_name)) {
+                                    final long id = addAppShortcut(db, values, parser);
+                                    added = id >= 0;
+                                } else {
+                                    Log.e(TAG, "Fallback groups can contain only favorites, found "
+                                            + fallback_item_name);
                                 }
-                            } else if (TAG_SHORTCUT.equals(folder_item_name) && folderId >= 0) {
-                                long id = addUriShortcut(db, values, ar);
-                                if (id >= 0) {
-                                    folderItems.add(id);
-                                }
-                            } else {
-                                throw new RuntimeException("Folders can " +
-                                        "contain only shortcuts");
                             }
-                            ar.recycle();
                         }
-                        // We can only have folders with >= 2 items, so we need to remove the
-                        // folder and clean up if less than 2 items were included, or some
-                        // failed to add, and less than 2 were actually added
-                        if (folderItems.size() < 2 && folderId >= 0) {
-                            // We just delete the folder and any items that made it
-                            deleteId(db, folderId);
-                            if (folderItems.size() > 0) {
-                                deleteId(db, folderItems.get(0));
+                    } else if (TAG_FOLDER.equals(name)) {
+                        // Folder contents are nested in this XML file
+                        added = loadFolder(db, values, res, parser);
+
+                    } else if (TAG_PARTNER_FOLDER.equals(name)) {
+                        // Folder contents come from an external XML resource
+                        final Partner partner = Partner.get(mPackageManager);
+                        if (partner != null) {
+                            final Resources partnerRes = partner.getResources();
+                            final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
+                                    "xml", partner.getPackageName());
+                            if (resId != 0) {
+                                final XmlResourceParser partnerParser = partnerRes.getXml(resId);
+                                beginDocument(partnerParser, TAG_FOLDER);
+                                added = loadFolder(db, values, partnerRes, partnerParser);
                             }
-                            added = false;
                         }
                     }
-                    if (added) i++;
-                    a.recycle();
+                    if (added) {
+                        long screenId = Long.parseLong(screen);
+                        // Keep track of the set of screens which need to be added to the db.
+                        if (!screenIds.contains(screenId) &&
+                                container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                            screenIds.add(screenId);
+                        }
+                        count++;
+                    }
                 }
             } catch (XmlPullParserException e) {
                 Log.w(TAG, "Got exception parsing favorites.", e);
@@ -1220,50 +1551,231 @@
             } catch (RuntimeException e) {
                 Log.w(TAG, "Got exception parsing favorites.", e);
             }
-
-            // Update the max item id after we have loaded the database
-            if (mMaxItemId == -1) {
-                mMaxItemId = initializeMaxItemId(db);
-            }
-
-            return i;
+            return count;
         }
 
-        private long addAppShortcut(SQLiteDatabase db, ContentValues values, TypedArray a,
-                PackageManager packageManager, Intent intent) {
-            long id = -1;
-            ActivityInfo info;
-            String packageName = a.getString(R.styleable.Favorite_packageName);
-            String className = a.getString(R.styleable.Favorite_className);
-            try {
-                ComponentName cn;
-                try {
-                    cn = new ComponentName(packageName, className);
-                    info = packageManager.getActivityInfo(cn, 0);
-                } catch (PackageManager.NameNotFoundException nnfe) {
-                    String[] packages = packageManager.currentToCanonicalPackageNames(
-                        new String[] { packageName });
-                    cn = new ComponentName(packages[0], className);
-                    info = packageManager.getActivityInfo(cn, 0);
+        /**
+         * Parse folder items starting at {@link XmlPullParser} location. Allow recursive
+         * includes of items.
+         */
+        private void addToFolder(SQLiteDatabase db, Resources res, XmlResourceParser parser,
+                ArrayList<Long> folderItems, long folderId) throws IOException, XmlPullParserException {
+            int type;
+            int folderDepth = parser.getDepth();
+            while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                    parser.getDepth() > folderDepth) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
                 }
-                id = generateNewItemId();
-                intent.setComponent(cn);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                values.put(Favorites.INTENT, intent.toUri(0));
-                values.put(Favorites.TITLE, info.loadLabel(packageManager).toString());
-                values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
-                values.put(Favorites.SPANX, 1);
-                values.put(Favorites.SPANY, 1);
-                values.put(Favorites._ID, generateNewItemId());
-                if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
+                final String tag = parser.getName();
+
+                final ContentValues childValues = new ContentValues();
+                childValues.put(LauncherSettings.Favorites.CONTAINER, folderId);
+
+                if (LOGD) {
+                    final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+                    final String uri = getAttributeValue(parser, ATTR_URI);
+                    Log.v(TAG, String.format(("%" + (2*(folderDepth+1)) + "s<%s \"%s\">"), "",
+                            tag, uri != null ? uri : pkg));
+                }
+
+                if (TAG_FAVORITE.equals(tag) && folderId >= 0) {
+                    final long id = addAppShortcut(db, childValues, parser);
+                    if (id >= 0) {
+                        folderItems.add(id);
+                    }
+                } else if (TAG_SHORTCUT.equals(tag) && folderId >= 0) {
+                    final long id = addUriShortcut(db, childValues, res, parser);
+                    if (id >= 0) {
+                        folderItems.add(id);
+                    }
+                } else if (TAG_INCLUDE.equals(tag) && folderId >= 0) {
+                    addToFolder(db, res, parser, folderItems, folderId);
+                } else {
+                    throw new RuntimeException("Folders can contain only shortcuts");
+                }
+            }
+        }
+
+        /**
+         * Parse folder starting at current {@link XmlPullParser} location.
+         */
+        private boolean loadFolder(SQLiteDatabase db, ContentValues values, Resources res,
+                XmlResourceParser parser) throws IOException, XmlPullParserException {
+            final String title;
+            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
+            if (titleResId != 0) {
+                title = res.getString(titleResId);
+            } else {
+                title = mContext.getResources().getString(R.string.folder_name);
+            }
+
+            values.put(LauncherSettings.Favorites.TITLE, title);
+            long folderId = addFolder(db, values);
+            boolean added = folderId >= 0;
+
+            ArrayList<Long> folderItems = new ArrayList<Long>();
+            addToFolder(db, res, parser, folderItems, folderId);
+
+            // We can only have folders with >= 2 items, so we need to remove the
+            // folder and clean up if less than 2 items were included, or some
+            // failed to add, and less than 2 were actually added
+            if (folderItems.size() < 2 && folderId >= 0) {
+                // Delete the folder
+                deleteId(db, folderId);
+
+                // If we have a single item, promote it to where the folder
+                // would have been.
+                if (folderItems.size() == 1) {
+                    final ContentValues childValues = new ContentValues();
+                    copyInteger(values, childValues, LauncherSettings.Favorites.CONTAINER);
+                    copyInteger(values, childValues, LauncherSettings.Favorites.SCREEN);
+                    copyInteger(values, childValues, LauncherSettings.Favorites.CELLX);
+                    copyInteger(values, childValues, LauncherSettings.Favorites.CELLY);
+
+                    final long id = folderItems.get(0);
+                    db.update(TABLE_FAVORITES, childValues,
+                            LauncherSettings.Favorites._ID + "=" + id, null);
+                } else {
+                    added = false;
+                }
+            }
+            return added;
+        }
+
+        // A meta shortcut attempts to resolve an intent specified as a URI in the XML, if a
+        // logical choice for what shortcut should be used for that intent exists, then it is
+        // added. Otherwise add nothing.
+        private long addAppShortcutByUri(SQLiteDatabase db, ContentValues values,
+                String intentUri) {
+            Intent metaIntent;
+            try {
+                metaIntent = Intent.parseUri(intentUri, 0);
+            } catch (URISyntaxException e) {
+                Log.e(TAG, "Unable to add meta-favorite: " + intentUri, e);
+                return -1;
+            }
+
+            ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent,
+                    PackageManager.MATCH_DEFAULT_ONLY);
+            final List<ResolveInfo> appList = mPackageManager.queryIntentActivities(
+                    metaIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+            // Verify that the result is an app and not just the resolver dialog asking which
+            // app to use.
+            if (wouldLaunchResolverActivity(resolved, appList)) {
+                // If only one of the results is a system app then choose that as the default.
+                final ResolveInfo systemApp = getSingleSystemActivity(appList);
+                if (systemApp == null) {
+                    // There is no logical choice for this meta-favorite, so rather than making
+                    // a bad choice just add nothing.
+                    Log.w(TAG, "No preference or single system activity found for "
+                            + metaIntent.toString());
                     return -1;
                 }
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Unable to add favorite: " + packageName +
-                        "/" + className, e);
+                resolved = systemApp;
             }
-            return id;
+            final ActivityInfo info = resolved.activityInfo;
+            final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName);
+            if (intent == null) {
+                return -1;
+            }
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+            return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(), intent);
+        }
+
+        private ResolveInfo getSingleSystemActivity(List<ResolveInfo> appList) {
+            ResolveInfo systemResolve = null;
+            final int N = appList.size();
+            for (int i = 0; i < N; ++i) {
+                try {
+                    ApplicationInfo info = mPackageManager.getApplicationInfo(
+                            appList.get(i).activityInfo.packageName, 0);
+                    if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        if (systemResolve != null) {
+                            return null;
+                        } else {
+                            systemResolve = appList.get(i);
+                        }
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Unable to get info about resolve results", e);
+                    return null;
+                }
+            }
+            return systemResolve;
+        }
+
+        private boolean wouldLaunchResolverActivity(ResolveInfo resolved,
+                List<ResolveInfo> appList) {
+            // If the list contains the above resolved activity, then it can't be
+            // ResolverActivity itself.
+            for (int i = 0; i < appList.size(); ++i) {
+                ResolveInfo tmp = appList.get(i);
+                if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
+                        && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private long addAppShortcut(SQLiteDatabase db, ContentValues values,
+                XmlResourceParser parser) {
+            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
+            final String uri = getAttributeValue(parser, ATTR_URI);
+
+            if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) {
+                ActivityInfo info;
+                try {
+                    ComponentName cn;
+                    try {
+                        cn = new ComponentName(packageName, className);
+                        info = mPackageManager.getActivityInfo(cn, 0);
+                    } catch (PackageManager.NameNotFoundException nnfe) {
+                        String[] packages = mPackageManager.currentToCanonicalPackageNames(
+                                new String[] { packageName });
+                        cn = new ComponentName(packages[0], className);
+                        info = mPackageManager.getActivityInfo(cn, 0);
+                    }
+                    final Intent intent = buildMainIntent();
+                    intent.setComponent(cn);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+                    return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(),
+                            intent);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Unable to add favorite: " + packageName +
+                            "/" + className, e);
+                }
+                return -1;
+            } else if (!TextUtils.isEmpty(uri)) {
+                // If no component specified try to find a shortcut to add from the URI.
+                return addAppShortcutByUri(db, values, uri);
+            } else {
+                Log.e(TAG, "Skipping invalid <favorite> with no component or uri");
+                return -1;
+            }
+        }
+
+        private long addAppShortcut(SQLiteDatabase db, ContentValues values, String title,
+                Intent intent) {
+            long id = generateNewItemId();
+            values.put(Favorites.INTENT, intent.toUri(0));
+            values.put(Favorites.TITLE, title);
+            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
+            values.put(Favorites.SPANX, 1);
+            values.put(Favorites.SPANY, 1);
+            values.put(Favorites._ID, id);
+            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
+                return -1;
+            } else {
+                return id;
+            }
         }
 
         private long addFolder(SQLiteDatabase db, ContentValues values) {
@@ -1305,23 +1817,12 @@
             return null;
         }
 
-        private boolean addSearchWidget(SQLiteDatabase db, ContentValues values) {
-            ComponentName cn = getSearchWidgetProvider();
-            return addAppWidget(db, values, cn, 4, 1, null);
-        }
+        private boolean addAppWidget(XmlResourceParser parser, int type,
+                SQLiteDatabase db, ContentValues values)
+                throws XmlPullParserException, IOException {
 
-        private boolean addClockWidget(SQLiteDatabase db, ContentValues values) {
-            ComponentName cn = new ComponentName("com.android.alarmclock",
-                    "com.android.alarmclock.AnalogAppWidgetProvider");
-            return addAppWidget(db, values, cn, 2, 2, null);
-        }
-
-        private boolean addAppWidget(XmlResourceParser parser, AttributeSet attrs, int type,
-                SQLiteDatabase db, ContentValues values, TypedArray a,
-                PackageManager packageManager) throws XmlPullParserException, IOException {
-
-            String packageName = a.getString(R.styleable.Favorite_packageName);
-            String className = a.getString(R.styleable.Favorite_className);
+            String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            String className = getAttributeValue(parser, ATTR_CLASS_NAME);
 
             if (packageName == null || className == null) {
                 return false;
@@ -1330,21 +1831,25 @@
             boolean hasPackage = true;
             ComponentName cn = new ComponentName(packageName, className);
             try {
-                packageManager.getReceiverInfo(cn, 0);
+                mPackageManager.getReceiverInfo(cn, 0);
             } catch (Exception e) {
-                String[] packages = packageManager.currentToCanonicalPackageNames(
+                String[] packages = mPackageManager.currentToCanonicalPackageNames(
                         new String[] { packageName });
                 cn = new ComponentName(packages[0], className);
                 try {
-                    packageManager.getReceiverInfo(cn, 0);
+                    mPackageManager.getReceiverInfo(cn, 0);
                 } catch (Exception e1) {
+                    System.out.println("Can't find widget provider: " + className);
                     hasPackage = false;
                 }
             }
 
             if (hasPackage) {
-                int spanX = a.getInt(R.styleable.Favorite_spanX, 0);
-                int spanY = a.getInt(R.styleable.Favorite_spanY, 0);
+                String spanX = getAttributeValue(parser, ATTR_SPAN_X);
+                String spanY = getAttributeValue(parser, ATTR_SPAN_Y);
+
+                values.put(Favorites.SPANX, spanX);
+                values.put(Favorites.SPANY, spanY);
 
                 // Read the extras
                 Bundle extras = new Bundle();
@@ -1355,10 +1860,9 @@
                         continue;
                     }
 
-                    TypedArray ar = mContext.obtainStyledAttributes(attrs, R.styleable.Extra);
                     if (TAG_EXTRA.equals(parser.getName())) {
-                        String key = ar.getString(R.styleable.Extra_key);
-                        String value = ar.getString(R.styleable.Extra_value);
+                        String key = getAttributeValue(parser, ATTR_KEY);
+                        String value = getAttributeValue(parser, ATTR_VALUE);
                         if (key != null && value != null) {
                             extras.putString(key, value);
                         } else {
@@ -1367,16 +1871,16 @@
                     } else {
                         throw new RuntimeException("Widgets can contain only extras");
                     }
-                    ar.recycle();
                 }
 
-                return addAppWidget(db, values, cn, spanX, spanY, extras);
+                return addAppWidget(db, values, cn, extras);
             }
 
             return false;
         }
+
         private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn,
-                int spanX, int spanY, Bundle extras) {
+               Bundle extras) {
             boolean allocatedAppWidgets = false;
             final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
 
@@ -1384,8 +1888,6 @@
                 int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
 
                 values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
-                values.put(Favorites.SPANX, spanX);
-                values.put(Favorites.SPANY, spanY);
                 values.put(Favorites.APPWIDGET_ID, appWidgetId);
                 values.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
                 values.put(Favorites._ID, generateNewItemId());
@@ -1411,17 +1913,15 @@
             return allocatedAppWidgets;
         }
 
-        private long addUriShortcut(SQLiteDatabase db, ContentValues values,
-                TypedArray a) {
-            Resources r = mContext.getResources();
-
-            final int iconResId = a.getResourceId(R.styleable.Favorite_icon, 0);
-            final int titleResId = a.getResourceId(R.styleable.Favorite_title, 0);
+        private long addUriShortcut(SQLiteDatabase db, ContentValues values, Resources res,
+                XmlResourceParser parser) {
+            final int iconResId = getAttributeResourceValue(parser, ATTR_ICON, 0);
+            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
 
             Intent intent;
             String uri = null;
             try {
-                uri = a.getString(R.styleable.Favorite_uri);
+                uri = getAttributeValue(parser, ATTR_URI);
                 intent = Intent.parseUri(uri, 0);
             } catch (URISyntaxException e) {
                 Log.w(TAG, "Shortcut has malformed uri: " + uri);
@@ -1436,13 +1936,13 @@
             long id = generateNewItemId();
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             values.put(Favorites.INTENT, intent.toUri(0));
-            values.put(Favorites.TITLE, r.getString(titleResId));
+            values.put(Favorites.TITLE, res.getString(titleResId));
             values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_SHORTCUT);
             values.put(Favorites.SPANX, 1);
             values.put(Favorites.SPANY, 1);
             values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
-            values.put(Favorites.ICON_PACKAGE, mContext.getPackageName());
-            values.put(Favorites.ICON_RESOURCE, r.getResourceName(iconResId));
+            values.put(Favorites.ICON_PACKAGE, res.getResourcePackageName(iconResId));
+            values.put(Favorites.ICON_RESOURCE, res.getResourceName(iconResId));
             values.put(Favorites._ID, id);
 
             if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
@@ -1451,7 +1951,7 @@
             return id;
         }
 
-        public void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
+        private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
             final ContentResolver resolver = mContext.getContentResolver();
             Cursor c = null;
             int count = 0;
@@ -1463,7 +1963,6 @@
                 // Ignore
             }
 
-
             // We already have a favorites database in the old provider
             if (c != null) {
                 try {
@@ -1495,6 +1994,8 @@
                                 = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
                         final int displayModeIndex
                                 = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
+                        final int profileIndex
+                                = c.getColumnIndex(LauncherSettings.Favorites.PROFILE_ID);
 
                         int i = 0;
                         int curX = 0;
@@ -1508,7 +2009,9 @@
 
                         final HashSet<String> seenIntents = new HashSet<String>(c.getCount());
 
-                        final ContentValues[] rows = new ContentValues[c.getCount()];
+                        final ArrayList<ContentValues> shortcuts = new ArrayList<ContentValues>();
+                        final ArrayList<ContentValues> folders = new ArrayList<ContentValues>();
+                        final SparseArray<ContentValues> hotseat = new SparseArray<ContentValues>();
 
                         while (c.moveToNext()) {
                             final int itemType = c.getInt(itemTypeIndex);
@@ -1523,33 +2026,65 @@
                             final int screen = c.getInt(screenIndex);
                             int container = c.getInt(containerIndex);
                             final String intentStr = c.getString(intentIndex);
+
+                            UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+                            UserHandleCompat userHandle;
+                            final long userSerialNumber;
+                            if (profileIndex != -1 && !c.isNull(profileIndex)) {
+                                userSerialNumber = c.getInt(profileIndex);
+                                userHandle = userManager.getUserForSerialNumber(userSerialNumber);
+                            } else {
+                                // Default to the serial number of this user, for older
+                                // shortcuts.
+                                userHandle = UserHandleCompat.myUserHandle();
+                                userSerialNumber = userManager.getSerialNumberForUser(userHandle);
+                            }
                             Launcher.addDumpLog(TAG, "migrating \""
-                                + c.getString(titleIndex) + "\": " + intentStr, true);
+                                + c.getString(titleIndex) + "\" ("
+                                + cellX + "," + cellY + "@"
+                                + LauncherSettings.Favorites.containerToString(container)
+                                + "/" + screen
+                                + "): " + intentStr, true);
 
                             if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+
+                                final Intent intent;
+                                final ComponentName cn;
+                                try {
+                                    intent = Intent.parseUri(intentStr, 0);
+                                } catch (URISyntaxException e) {
+                                    // bogus intent?
+                                    Launcher.addDumpLog(TAG,
+                                            "skipping invalid intent uri", true);
+                                    continue;
+                                }
+
+                                cn = intent.getComponent();
                                 if (TextUtils.isEmpty(intentStr)) {
                                     // no intent? no icon
                                     Launcher.addDumpLog(TAG, "skipping empty intent", true);
                                     continue;
-                                } else {
-                                    try {
-                                        // Canonicalize
-                                        final Intent intent = Intent.parseUri(intentStr, 0);
-                                        // the Play Store sets the package parameter, but Launcher
-                                        // does not, so we clear that out to keep them the same
-                                        intent.setPackage(null);
-                                        final String key = intent.toUri(0);
-                                        if (seenIntents.contains(key)) {
-                                            Launcher.addDumpLog(TAG, "skipping duplicate", true);
-                                            continue;
-                                        } else {
-                                            seenIntents.add(key);
-                                        }
-                                    } catch (URISyntaxException e) {
-                                        // bogus intent?
-                                        Launcher.addDumpLog(TAG,
-                                                "skipping invalid intent uri", true);
+                                } else if (cn != null &&
+                                        !LauncherModel.isValidPackageActivity(mContext, cn,
+                                                userHandle)) {
+                                    // component no longer exists.
+                                    Launcher.addDumpLog(TAG, "skipping item whose component " +
+                                            "no longer exists.", true);
+                                    continue;
+                                } else if (container ==
+                                        LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                    // Dedupe icons directly on the workspace
+
+                                    // Canonicalize
+                                    // the Play Store sets the package parameter, but Launcher
+                                    // does not, so we clear that out to keep them the same
+                                    intent.setPackage(null);
+                                    final String key = intent.toUri(0);
+                                    if (seenIntents.contains(key)) {
+                                        Launcher.addDumpLog(TAG, "skipping duplicate", true);
                                         continue;
+                                    } else {
+                                        seenIntents.add(key);
                                     }
                                 }
                             }
@@ -1570,11 +2105,10 @@
                             values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
                             values.put(LauncherSettings.Favorites.DISPLAY_MODE,
                                     c.getInt(displayModeIndex));
+                            values.put(LauncherSettings.Favorites.PROFILE_ID, userSerialNumber);
 
-                            if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
-                                    && screen >= hotseatWidth) {
-                                // no room for you in the hotseat? it's off to the desktop with you
-                                container = Favorites.CONTAINER_DESKTOP;
+                            if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                                hotseat.put(screen, values);
                             }
 
                             if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
@@ -1583,32 +2117,78 @@
                                 values.put(LauncherSettings.Favorites.CELLX, cellX);
                                 values.put(LauncherSettings.Favorites.CELLY, cellY);
                             } else {
-                                values.put(LauncherSettings.Favorites.SCREEN, curScreen);
-                                values.put(LauncherSettings.Favorites.CELLX, curX);
-                                values.put(LauncherSettings.Favorites.CELLY, curY);
-                                curX = (curX + 1) % width;
-                                if (curX == 0) {
-                                    curY = (curY + 1);
-                                }
-                                // Leave the last row of icons blank on screen 0
-                                if (curScreen == 0 && curY == height - 1 || curY == height) {
-                                    curScreen = (int) generateNewScreenId();
-                                    curY = 0;
-                                }
+                                // For items contained directly on one of the workspace screen,
+                                // we'll determine their location (screen, x, y) in a second pass.
                             }
 
                             values.put(LauncherSettings.Favorites.CONTAINER, container);
 
-                            rows[i++] = values;
+                            if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+                                shortcuts.add(values);
+                            } else {
+                                folders.add(values);
+                            }
                         }
 
-                        if (i > 0) {
+                        // Now that we have all the hotseat icons, let's go through them left-right
+                        // and assign valid locations for them in the new hotseat
+                        final int N = hotseat.size();
+                        for (int idx=0; idx<N; idx++) {
+                            int hotseatX = hotseat.keyAt(idx);
+                            ContentValues values = hotseat.valueAt(idx);
+
+                            if (hotseatX == grid.hotseatAllAppsRank) {
+                                // let's drop this in the next available hole in the hotseat
+                                while (++hotseatX < hotseatWidth) {
+                                    if (hotseat.get(hotseatX) == null) {
+                                        // found a spot! move it here
+                                        values.put(LauncherSettings.Favorites.SCREEN,
+                                                hotseatX);
+                                        break;
+                                    }
+                                }
+                            }
+                            if (hotseatX >= hotseatWidth) {
+                                // no room for you in the hotseat? it's off to the desktop with you
+                                values.put(LauncherSettings.Favorites.CONTAINER,
+                                           Favorites.CONTAINER_DESKTOP);
+                            }
+                        }
+
+                        final ArrayList<ContentValues> allItems = new ArrayList<ContentValues>();
+                        // Folders first
+                        allItems.addAll(folders);
+                        // Then shortcuts
+                        allItems.addAll(shortcuts);
+
+                        // Layout all the folders
+                        for (ContentValues values: allItems) {
+                            if (values.getAsInteger(LauncherSettings.Favorites.CONTAINER) !=
+                                    LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                // Hotseat items and folder items have already had their
+                                // location information set. Nothing to be done here.
+                                continue;
+                            }
+                            values.put(LauncherSettings.Favorites.SCREEN, curScreen);
+                            values.put(LauncherSettings.Favorites.CELLX, curX);
+                            values.put(LauncherSettings.Favorites.CELLY, curY);
+                            curX = (curX + 1) % width;
+                            if (curX == 0) {
+                                curY = (curY + 1);
+                            }
+                            // Leave the last row of icons blank on every screen
+                            if (curY == height - 1) {
+                                curScreen = (int) generateNewScreenId();
+                                curY = 0;
+                            }
+                        }
+
+                        if (allItems.size() > 0) {
                             db.beginTransaction();
                             try {
-                                final int N = rows.length;
-                                for (i = 0; i < N; i++) {
-                                    if (rows[i] == null) continue;
-                                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i])
+                                for (ContentValues row: allItems) {
+                                    if (row == null) continue;
+                                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, row)
                                             < 0) {
                                         return;
                                     } else {
@@ -1659,7 +2239,7 @@
      * Build a query string that will match any row where the column matches
      * anything in the values list.
      */
-    static String buildOrWhereString(String column, int[] values) {
+    private static String buildOrWhereString(String column, int[] values) {
         StringBuilder selectWhere = new StringBuilder();
         for (int i = values.length - 1; i >= 0; i--) {
             selectWhere.append(column).append("=").append(values[i]);
@@ -1670,6 +2250,38 @@
         return selectWhere.toString();
     }
 
+    /**
+     * Return attribute value, attempting launcher-specific namespace first
+     * before falling back to anonymous attribute.
+     */
+    private static String getAttributeValue(XmlResourceParser parser, String attribute) {
+        String value = parser.getAttributeValue(
+                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
+        if (value == null) {
+            value = parser.getAttributeValue(null, attribute);
+        }
+        return value;
+    }
+
+    /**
+     * Return attribute resource value, attempting launcher-specific namespace
+     * first before falling back to anonymous attribute.
+     */
+    private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
+            int defaultValue) {
+        int value = parser.getAttributeResourceValue(
+                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
+                defaultValue);
+        if (value == defaultValue) {
+            value = parser.getAttributeResourceValue(null, attribute, defaultValue);
+        }
+        return value;
+    }
+
+    private static void copyInteger(ContentValues from, ContentValues to, String key) {
+        to.put(key, from.getAsInteger(key));
+    }
+
     static class SqlArguments {
         public final String table;
         public final String where;
@@ -1701,4 +2313,29 @@
             }
         }
     }
+
+    static interface WorkspaceLoader {
+        /**
+         * @param screenIds A mutable list of screen its
+         * @return the number of workspace items added.
+         */
+        int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds);
+    }
+
+    private static class SimpleWorkspaceLoader implements WorkspaceLoader {
+        private final Resources mRes;
+        private final int mWorkspaceId;
+        private final DatabaseHelper mHelper;
+
+        SimpleWorkspaceLoader(DatabaseHelper helper, Resources res, int workspaceId) {
+            mHelper = helper;
+            mRes = res;
+            mWorkspaceId = workspaceId;
+        }
+
+        @Override
+        public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
+            return mHelper.loadFavoritesRecursive(db, mRes, mWorkspaceId, screenIds);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/LauncherProviderChangeListener.java b/src/com/android/launcher3/LauncherProviderChangeListener.java
new file mode 100644
index 0000000..0de96fb
--- /dev/null
+++ b/src/com/android/launcher3/LauncherProviderChangeListener.java
@@ -0,0 +1,11 @@
+package com.android.launcher3;
+
+/**
+ * This class is a listener for {@link LauncherProvider} changes. It gets notified in the
+ * sendNotify method. This listener is needed because by default the Launcher suppresses
+ * standard data change callbacks.
+ */
+public interface LauncherProviderChangeListener {
+
+    public void onLauncherProviderChange();
+}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 988e5ef..3553702 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -171,6 +171,14 @@
         static final int CONTAINER_DESKTOP = -100;
         static final int CONTAINER_HOTSEAT = -101;
 
+        static final String containerToString(int container) {
+            switch (container) {
+                case CONTAINER_DESKTOP: return "desktop";
+                case CONTAINER_HOTSEAT: return "hotseat";
+                default: return String.valueOf(container);
+            }
+        }
+
         /**
          * The screen holding the favorite (if container is CONTAINER_DESKTOP)
          * <P>Type: INTEGER</P>
@@ -204,6 +212,14 @@
         static final String SPANY = "spanY";
 
         /**
+         * The profile id of the item in the cell.
+         * <P>
+         * Type: INTEGER
+         * </P>
+         */
+        static final String PROFILE_ID = "profileId";
+
+        /**
          * The favorite is a user created folder
          */
         static final int ITEM_TYPE_FOLDER = 2;
@@ -275,5 +291,11 @@
          * @see android.provider.LiveFolders#DISPLAY_MODE_LIST
          */
         static final String DISPLAY_MODE = "displayMode";
+
+        /**
+         * Boolean indicating that his item was restored and not yet successfully bound.
+         * <P>Type: INTEGER</P>
+         */
+        static final String RESTORED = "restored";
     }
 }
diff --git a/src/com/android/launcher3/LogAccelerateInterpolator.java b/src/com/android/launcher3/LogAccelerateInterpolator.java
new file mode 100644
index 0000000..c3bbfa5
--- /dev/null
+++ b/src/com/android/launcher3/LogAccelerateInterpolator.java
@@ -0,0 +1,25 @@
+package com.android.launcher3;
+
+import android.animation.TimeInterpolator;
+
+public class LogAccelerateInterpolator implements TimeInterpolator {
+
+    int mBase;
+    int mDrift;
+    final float mLogScale;
+
+    public LogAccelerateInterpolator(int base, int drift) {
+        mBase = base;
+        mDrift = drift;
+        mLogScale = 1f / computeLog(1, mBase, mDrift);
+    }
+
+    static float computeLog(float t, int base, int drift) {
+        return (float) -Math.pow(base, -t) + 1 + (drift * t);
+    }
+
+    @Override
+    public float getInterpolation(float t) {
+        return 1 - computeLog(1 - t, mBase, mDrift) * mLogScale;
+    }
+}
diff --git a/src/com/android/launcher3/LogDecelerateInterpolator.java b/src/com/android/launcher3/LogDecelerateInterpolator.java
new file mode 100644
index 0000000..4c5f6f0
--- /dev/null
+++ b/src/com/android/launcher3/LogDecelerateInterpolator.java
@@ -0,0 +1,26 @@
+package com.android.launcher3;
+
+import android.animation.TimeInterpolator;
+
+public class LogDecelerateInterpolator implements TimeInterpolator {
+
+    int mBase;
+    int mDrift;
+    final float mLogScale;
+
+    public LogDecelerateInterpolator(int base, int drift) {
+        mBase = base;
+        mDrift = drift;
+
+        mLogScale = 1f / computeLog(1, mBase, mDrift);
+    }
+
+    static float computeLog(float t, int base, int drift) {
+        return (float) -Math.pow(base, -t) + 1 + (drift * t);
+    }
+
+    @Override
+    public float getInterpolation(float t) {
+        return computeLog(t, mBase, mDrift) * mLogScale;
+    }
+}
diff --git a/src/com/android/launcher3/MainThreadExecutor.java b/src/com/android/launcher3/MainThreadExecutor.java
new file mode 100644
index 0000000..866b17c
--- /dev/null
+++ b/src/com/android/launcher3/MainThreadExecutor.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An executor service that executes its tasks on the main thread.
+ *
+ * Shutting down this executor is not supported.
+ */
+public class MainThreadExecutor extends AbstractExecutorService {
+
+    private Handler mHandler = new Handler(Looper.getMainLooper());
+
+    @Override
+    public void execute(Runnable runnable) {
+        if (Looper.getMainLooper() == Looper.myLooper()) {
+            runnable.run();
+        } else {
+            mHandler.post(runnable);
+        }
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public void shutdown() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public List<Runnable> shutdownNow() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isShutdown() {
+        return false;
+    }
+
+    @Override
+    public boolean isTerminated() {
+        return false;
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 8d5d8dd..48fc0c9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -74,11 +74,12 @@
     private static final int MIN_LENGTH_FOR_FLING = 25;
 
     protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
+    protected static final int OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION = 350;
     protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
     protected static final float NANOTIME_DIV = 1000000000.0f;
 
     private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
-    private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
+    private static final float OVERSCROLL_DAMP_FACTOR = 0.07f;
 
     private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
     // The page is moved more than halfway, automatically move to the next page on touch up.
@@ -152,16 +153,11 @@
     protected int mTouchState = TOUCH_STATE_REST;
     protected boolean mForceScreenScrolled = false;
 
-
     protected OnLongClickListener mLongClickListener;
 
     protected int mTouchSlop;
     private int mPagingTouchSlop;
     private int mMaximumVelocity;
-    protected int mPageLayoutPaddingTop;
-    protected int mPageLayoutPaddingBottom;
-    protected int mPageLayoutPaddingLeft;
-    protected int mPageLayoutPaddingRight;
     protected int mPageLayoutWidthGap;
     protected int mPageLayoutHeightGap;
     protected int mCellCountX = 0;
@@ -171,6 +167,7 @@
     protected int mUnboundedScrollX;
     protected int[] mTempVisiblePagesRange = new int[2];
     protected boolean mForceDrawAllChildrenNextFrame;
+    private boolean mSpacePagesAutomatically = false;
 
     // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. Otherwise
     // it is equal to the scaled overscroll position. We use a separate value so as to prevent
@@ -283,14 +280,6 @@
         TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.PagedView, defStyle, 0);
 
-        mPageLayoutPaddingTop = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingTop, 0);
-        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingBottom, 0);
-        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingLeft, 0);
-        mPageLayoutPaddingRight = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingRight, 0);
         mPageLayoutWidthGap = a.getDimensionPixelSize(
                 R.styleable.PagedView_pageLayoutWidthGap, 0);
         mPageLayoutHeightGap = a.getDimensionPixelSize(
@@ -339,8 +328,9 @@
 
         // Hook up the page indicator
         ViewGroup parent = (ViewGroup) getParent();
+        ViewGroup grandParent = (ViewGroup) parent.getParent();
         if (mPageIndicator == null && mPageIndicatorViewId > -1) {
-            mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId);
+            mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId);
             mPageIndicator.removeAllMarkers(mAllowPagedViewAnimations);
 
             ArrayList<PageIndicator.PageMarkerResources> markers =
@@ -547,6 +537,19 @@
         mNextPage = INVALID_PAGE;
     }
 
+    private int validateNewPage(int newPage) {
+        int validatedPage = newPage;
+        // When in free scroll mode, we need to clamp to the free scroll page range.
+        if (mFreeScroll) {
+            getFreeScrollPageRange(mTempVisiblePagesRange);
+            validatedPage = Math.max(mTempVisiblePagesRange[0],
+                    Math.min(newPage, mTempVisiblePagesRange[1]));
+        }
+        // Ensure that it is clamped by the actual set of children in all cases
+        validatedPage = Math.max(0, Math.min(validatedPage, getPageCount() - 1));
+        return validatedPage;
+    }
+
     /**
      * Sets the current page.
      */
@@ -560,7 +563,7 @@
             return;
         }
         mForceScreenScrolled = true;
-        mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        mCurrentPage = validateNewPage(currentPage);
         updateCurrentPageScroll();
         notifyPageSwitchListener();
         invalidate();
@@ -591,8 +594,11 @@
 
     private void updatePageIndicator() {
         // Update the page indicator (when we aren't reordering)
-        if (mPageIndicator != null && !isReordering(false)) {
-            mPageIndicator.setActiveMarker(getNextPage());
+        if (mPageIndicator != null) {
+            mPageIndicator.setContentDescription(getPageIndicatorDescription());
+            if (!isReordering(false)) {
+                mPageIndicator.setActiveMarker(getNextPage());
+            }
         }
     }
     protected void pageBeginMoving() {
@@ -727,7 +733,7 @@
         } else if (mNextPage != INVALID_PAGE) {
             sendScrollAccessibilityEvent();
 
-            mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
+            mCurrentPage = validateNewPage(mNextPage);
             mNextPage = INVALID_PAGE;
             notifyPageSwitchListener();
 
@@ -843,6 +849,7 @@
         final int verticalPadding = getPaddingTop() + getPaddingBottom();
         final int horizontalPadding = getPaddingLeft() + getPaddingRight();
 
+        int referenceChildWidth = 0;
         // The children are given the same width and height as the workspace
         // unless they were set to WRAP_CONTENT
         if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
@@ -887,6 +894,9 @@
                     childWidth = getViewportWidth() - mInsets.left - mInsets.right;
                     childHeight = getViewportHeight();
                 }
+                if (referenceChildWidth == 0) {
+                    referenceChildWidth = childWidth;
+                }
 
                 final int childWidthMeasureSpec =
                         MeasureSpec.makeMeasureSpec(childWidth, childWidthMode);
@@ -895,9 +905,24 @@
                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
             }
         }
+        if (mSpacePagesAutomatically) {
+            int spacing = (getViewportWidth() - mInsets.left - mInsets.right
+                    - referenceChildWidth) / 2;
+            if (spacing >= 0) {
+                setPageSpacing(spacing);
+            }
+            mSpacePagesAutomatically = false;
+        }
         setMeasuredDimension(scaledWidthSize, scaledHeightSize);
     }
 
+    /**
+     * This method should be called once before first layout / measure pass.
+     */
+    protected void setSinglePageInViewport() {
+        mSpacePagesAutomatically = true;
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         if (!mIsDataReady || getChildCount() == 0) {
@@ -974,9 +999,7 @@
         }
 
         if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
-            setHorizontalScrollBarEnabled(false);
             updateCurrentPageScroll();
-            setHorizontalScrollBarEnabled(true);
             mFirstLayout = false;
         }
 
@@ -1105,7 +1128,7 @@
         return offset;
     }
 
-    protected void getOverviewModePages(int[] range) {
+    protected void getFreeScrollPageRange(int[] range) {
         range[0] = 0;
         range[1] = Math.max(0, getChildCount() - 1);
     }
@@ -1158,7 +1181,7 @@
     }
 
     protected boolean shouldDrawChild(View child) {
-        return child.getAlpha() > 0 && child.getVisibility() == VISIBLE;
+        return child.getVisibility() == VISIBLE;
     }
 
     @Override
@@ -1580,29 +1603,20 @@
         return f * f * f + 1.0f;
     }
 
-    protected void acceleratedOverScroll(float amount) {
+    protected float acceleratedOverFactor(float amount) {
         int screenSize = getViewportWidth();
 
         // We want to reach the max over scroll effect when the user has
         // over scrolled half the size of the screen
         float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
 
-        if (f == 0) return;
+        if (f == 0) return 0;
 
         // Clamp this factor, f, to -1 < f < 1
         if (Math.abs(f) >= 1) {
             f /= Math.abs(f);
         }
-
-        int overScrollAmount = (int) Math.round(f * screenSize);
-        if (amount < 0) {
-            mOverScrollX = overScrollAmount;
-            super.scrollTo(0, getScrollY());
-        } else {
-            mOverScrollX = mMaxScrollX + overScrollAmount;
-            super.scrollTo(mMaxScrollX, getScrollY());
-        }
-        invalidate();
+        return f;
     }
 
     protected void dampedOverScroll(float amount) {
@@ -1621,10 +1635,10 @@
         int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
         if (amount < 0) {
             mOverScrollX = overScrollAmount;
-            super.scrollTo(0, getScrollY());
+            super.scrollTo(mOverScrollX, getScrollY());
         } else {
             mOverScrollX = mMaxScrollX + overScrollAmount;
-            super.scrollTo(mMaxScrollX, getScrollY());
+            super.scrollTo(mOverScrollX, getScrollY());
         }
         invalidate();
     }
@@ -1650,7 +1664,7 @@
     }
 
     void updateFreescrollBounds() {
-        getOverviewModePages(mTempVisiblePagesRange);
+        getFreeScrollPageRange(mTempVisiblePagesRange);
         if (isLayoutRtl()) {
             mFreeScrollMinScrollX = getScrollForPage(mTempVisiblePagesRange[1]);
             mFreeScrollMaxScrollX = getScrollForPage(mTempVisiblePagesRange[0]);
@@ -1665,7 +1679,7 @@
 
         if (mFreeScroll) {
             updateFreescrollBounds();
-            getOverviewModePages(mTempVisiblePagesRange);
+            getFreeScrollPageRange(mTempVisiblePagesRange);
             if (getCurrentPage() < mTempVisiblePagesRange[0]) {
                 setCurrentPage(mTempVisiblePagesRange[0]);
             } else if (getCurrentPage() > mTempVisiblePagesRange[1]) {
@@ -1684,7 +1698,7 @@
         if (mDragView != null) {
             int dragX = (int) (mDragView.getLeft() + (mDragView.getMeasuredWidth() / 2)
                     + mDragView.getTranslationX());
-            getOverviewModePages(mTempVisiblePagesRange);
+            getFreeScrollPageRange(mTempVisiblePagesRange);
             int minDistance = Integer.MAX_VALUE;
             int minIndex = indexOfChild(mDragView);
             for (int i = mTempVisiblePagesRange[0]; i <= mTempVisiblePagesRange[1]; i++) {
@@ -1801,7 +1815,7 @@
                         !isHoveringOverDelete) {
                     mTempVisiblePagesRange[0] = 0;
                     mTempVisiblePagesRange[1] = getPageCount() - 1;
-                    getOverviewModePages(mTempVisiblePagesRange);
+                    getFreeScrollPageRange(mTempVisiblePagesRange);
                     if (mTempVisiblePagesRange[0] <= pageUnderPointIndex &&
                             pageUnderPointIndex <= mTempVisiblePagesRange[1] &&
                             pageUnderPointIndex != mSidePageHoverIndex && mScroller.isFinished()) {
@@ -2124,8 +2138,20 @@
         return minDistanceFromScreenCenterIndex;
     }
 
+    protected boolean isInOverScroll() {
+        return (mOverScrollX > mMaxScrollX || mOverScrollX < 0);
+    }
+
+    protected int getPageSnapDuration() {
+        if (isInOverScroll()) {
+            return OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION;
+        }
+        return PAGE_SNAP_ANIMATION_DURATION;
+
+    }
+
     protected void snapToDestination() {
-        snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
+        snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration());
     }
 
     private static class ScrollInterpolator implements Interpolator {
@@ -2149,17 +2175,17 @@
     }
 
     protected void snapToPageWithVelocity(int whichPage, int velocity) {
-        whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
+        whichPage = validateNewPage(whichPage);
         int halfScreenSize = getViewportWidth() / 2;
 
         final int newX = getScrollForPage(whichPage);
         int delta = newX - mUnboundedScrollX;
         int duration = 0;
 
-        if (Math.abs(velocity) < mMinFlingVelocity) {
+        if (Math.abs(velocity) < mMinFlingVelocity || isInOverScroll()) {
             // If the velocity is low enough, then treat this more as an automatic page advance
             // as opposed to an apparent physical response to flinging
-            snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+            snapToPage(whichPage, getPageSnapDuration());
             return;
         }
 
@@ -2183,11 +2209,11 @@
     }
 
     protected void snapToPage(int whichPage) {
-        snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+        snapToPage(whichPage, getPageSnapDuration());
     }
 
     protected void snapToPageImmediately(int whichPage) {
-        snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null);
+        snapToPage(whichPage, getPageSnapDuration(), true, null);
     }
 
     protected void snapToPage(int whichPage, int duration) {
@@ -2200,7 +2226,7 @@
 
     protected void snapToPage(int whichPage, int duration, boolean immediate,
             TimeInterpolator interpolator) {
-        whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
+        whichPage = validateNewPage(whichPage);
 
         int newX = getScrollForPage(whichPage);
         final int sX = mUnboundedScrollX;
@@ -2214,6 +2240,8 @@
 
     protected void snapToPage(int whichPage, int delta, int duration, boolean immediate,
             TimeInterpolator interpolator) {
+        whichPage = validateNewPage(whichPage);
+
         mNextPage = whichPage;
         View focusedChild = getFocusedChild();
         if (focusedChild != null && whichPage != mCurrentPage &&
@@ -2482,11 +2510,11 @@
     public boolean startReordering(View v) {
         int dragViewIndex = indexOfChild(v);
 
-        if (mTouchState != TOUCH_STATE_REST) return false;
+        if (mTouchState != TOUCH_STATE_REST || dragViewIndex == -1) return false;
 
         mTempVisiblePagesRange[0] = 0;
         mTempVisiblePagesRange[1] = getPageCount() - 1;
-        getOverviewModePages(mTempVisiblePagesRange);
+        getFreeScrollPageRange(mTempVisiblePagesRange);
         mReorderingStarted = true;
 
         // Check if we are within the reordering range
@@ -2619,7 +2647,7 @@
                 // in the layout)
                 // NOTE: We can make an assumption here because we have side-bound pages that we
                 //       will always have pages to animate in from the left
-                getOverviewModePages(mTempVisiblePagesRange);
+                getFreeScrollPageRange(mTempVisiblePagesRange);
                 boolean isLastWidgetPage = (mTempVisiblePagesRange[0] == mTempVisiblePagesRange[1]);
                 boolean slideFromLeft = (isLastWidgetPage ||
                         dragViewIndex > mTempVisiblePagesRange[0]);
diff --git a/src/com/android/launcher3/PagedViewGridLayout.java b/src/com/android/launcher3/PagedViewGridLayout.java
index b286861..f69fa56 100644
--- a/src/com/android/launcher3/PagedViewGridLayout.java
+++ b/src/com/android/launcher3/PagedViewGridLayout.java
@@ -56,18 +56,6 @@
         }
     }
 
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // PagedView currently has issues with different-sized pages since it calculates the
-        // offset of each page to scroll to before it updates the actual size of each page
-        // (which can change depending on the content if the contents aren't a fixed size).
-        // We work around this by having a minimum size on each widget page).
-        int widthSpecSize = Math.min(getSuggestedMinimumWidth(),
-                MeasureSpec.getSize(widthMeasureSpec));
-        int widthSpecMode = MeasureSpec.EXACTLY;
-        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
-                heightMeasureSpec);
-    }
-
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
diff --git a/src/com/android/launcher3/PagedViewIcon.java b/src/com/android/launcher3/PagedViewIcon.java
deleted file mode 100644
index f7cb997..0000000
--- a/src/com/android/launcher3/PagedViewIcon.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Region;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.widget.TextView;
-
-/**
- * An icon on a PagedView, specifically for items in the launcher's paged view (with compound
- * drawables on the top).
- */
-public class PagedViewIcon extends TextView {
-    /** A simple callback interface to allow a PagedViewIcon to notify when it has been pressed */
-    public static interface PressedCallback {
-        void iconPressed(PagedViewIcon icon);
-    }
-
-    @SuppressWarnings("unused")
-    private static final String TAG = "PagedViewIcon";
-    private static final float PRESS_ALPHA = 0.4f;
-
-    private PagedViewIcon.PressedCallback mPressedCallback;
-    private boolean mLockDrawableState = false;
-
-    private Bitmap mIcon;
-
-    public PagedViewIcon(Context context) {
-        this(context, null);
-    }
-
-    public PagedViewIcon(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    public void onFinishInflate() {
-        super.onFinishInflate();
-
-        // Ensure we are using the right text size
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
-    }
-
-    public void applyFromApplicationInfo(AppInfo info, boolean scaleUp,
-            PagedViewIcon.PressedCallback cb) {
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
-        mIcon = info.iconBitmap;
-        mPressedCallback = cb;
-        Drawable icon = Utilities.createIconDrawable(mIcon);
-        icon.setBounds(0, 0, grid.allAppsIconSizePx, grid.allAppsIconSizePx);
-        setCompoundDrawables(null, icon, null, null);
-        setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
-        setText(info.title);
-        setTag(info);
-    }
-
-    public void lockDrawableState() {
-        mLockDrawableState = true;
-    }
-
-    public void resetDrawableState() {
-        mLockDrawableState = false;
-        post(new Runnable() {
-            @Override
-            public void run() {
-                refreshDrawableState();
-            }
-        });
-    }
-
-    protected void drawableStateChanged() {
-        super.drawableStateChanged();
-
-        // We keep in the pressed state until resetDrawableState() is called to reset the press
-        // feedback
-        if (isPressed()) {
-            setAlpha(PRESS_ALPHA);
-            if (mPressedCallback != null) {
-                mPressedCallback.iconPressed(this);
-            }
-        } else if (!mLockDrawableState) {
-            setAlpha(1f);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        // If text is transparent, don't draw any shadow
-        if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) {
-            getPaint().clearShadowLayer();
-            super.draw(canvas);
-            return;
-        }
-
-        // We enhance the shadow by drawing the shadow twice
-        getPaint().setShadowLayer(BubbleTextView.SHADOW_LARGE_RADIUS, 0.0f,
-                BubbleTextView.SHADOW_Y_OFFSET, BubbleTextView.SHADOW_LARGE_COLOUR);
-        super.draw(canvas);
-        canvas.save(Canvas.CLIP_SAVE_FLAG);
-        canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
-                getScrollX() + getWidth(),
-                getScrollY() + getHeight(), Region.Op.INTERSECT);
-        getPaint().setShadowLayer(BubbleTextView.SHADOW_SMALL_RADIUS, 0.0f, 0.0f,
-                BubbleTextView.SHADOW_SMALL_COLOUR);
-        super.draw(canvas);
-        canvas.restore();
-    }
-}
diff --git a/src/com/android/launcher3/PagedViewIconCache.java b/src/com/android/launcher3/PagedViewIconCache.java
deleted file mode 100644
index 93887ea..0000000
--- a/src/com/android/launcher3/PagedViewIconCache.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.pm.ComponentInfo;
-import android.content.pm.ResolveInfo;
-import android.graphics.Bitmap;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Simple cache mechanism for PagedView outlines.
- */
-public class PagedViewIconCache {
-    public static class Key {
-        public enum Type {
-            ApplicationInfoKey,
-            AppWidgetProviderInfoKey,
-            ResolveInfoKey
-        }
-        private final ComponentName mComponentName;
-        private final Type mType;
-
-        public Key(AppInfo info) {
-            mComponentName = info.componentName;
-            mType = Type.ApplicationInfoKey;
-        }
-        public Key(ResolveInfo info) {
-            final ComponentInfo ci = info.activityInfo != null ? info.activityInfo :
-                info.serviceInfo;
-            mComponentName = new ComponentName(ci.packageName, ci.name);
-            mType = Type.ResolveInfoKey;
-        }
-        public Key(AppWidgetProviderInfo info) {
-            mComponentName = info.provider;
-            mType = Type.AppWidgetProviderInfoKey;
-        }
-
-        private ComponentName getComponentName() {
-            return mComponentName;
-        }
-        public boolean isKeyType(Type t) {
-            return (mType == t);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof Key) {
-                Key k = (Key) o;
-                return mComponentName.equals(k.mComponentName);
-            }
-            return super.equals(o);
-        }
-        @Override
-        public int hashCode() {
-            return getComponentName().hashCode();
-        }
-    }
-
-    private final HashMap<Key, Bitmap> mIconOutlineCache = new HashMap<Key, Bitmap>();
-
-    public void clear() {
-        for (Key key : mIconOutlineCache.keySet()) {
-            mIconOutlineCache.get(key).recycle();
-        }
-        mIconOutlineCache.clear();
-    }
-    private void retainAll(HashSet<Key> keysToKeep, Key.Type t) {
-        HashSet<Key> keysToRemove = new HashSet<Key>(mIconOutlineCache.keySet());
-        keysToRemove.removeAll(keysToKeep);
-        for (Key key : keysToRemove) {
-            if (key.isKeyType(t)) {
-                mIconOutlineCache.get(key).recycle();
-                mIconOutlineCache.remove(key);
-            }
-        }
-    }
-    /** Removes all the keys to applications that aren't in the passed in collection */
-    public void retainAllApps(ArrayList<AppInfo> keys) {
-        HashSet<Key> keysSet = new HashSet<Key>();
-        for (AppInfo info : keys) {
-            keysSet.add(new Key(info));
-        }
-        retainAll(keysSet, Key.Type.ApplicationInfoKey);
-    }
-    /** Removes all the keys to shortcuts that aren't in the passed in collection */
-    public void retainAllShortcuts(List<ResolveInfo> keys) {
-        HashSet<Key> keysSet = new HashSet<Key>();
-        for (ResolveInfo info : keys) {
-            keysSet.add(new Key(info));
-        }
-        retainAll(keysSet, Key.Type.ResolveInfoKey);
-    }
-    /** Removes all the keys to widgets that aren't in the passed in collection */
-    public void retainAllAppWidgets(List<AppWidgetProviderInfo> keys) {
-        HashSet<Key> keysSet = new HashSet<Key>();
-        for (AppWidgetProviderInfo info : keys) {
-            keysSet.add(new Key(info));
-        }
-        retainAll(keysSet, Key.Type.AppWidgetProviderInfoKey);
-    }
-    public void addOutline(Key key, Bitmap b) {
-        mIconOutlineCache.put(key, b);
-    }
-    public void removeOutline(Key key) {
-        if (mIconOutlineCache.containsKey(key)) {
-            mIconOutlineCache.get(key).recycle();
-            mIconOutlineCache.remove(key);
-        }
-    }
-    public Bitmap getOutline(Key key) {
-        return mIconOutlineCache.get(key);
-    }
-}
diff --git a/src/com/android/launcher3/PagedViewWidget.java b/src/com/android/launcher3/PagedViewWidget.java
index db4aeb9..e6e11a3 100644
--- a/src/com/android/launcher3/PagedViewWidget.java
+++ b/src/com/android/launcher3/PagedViewWidget.java
@@ -30,6 +30,8 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+
 /**
  * The linear layout used strictly for the widget/wallpaper tab of the customization tray
  */
@@ -127,7 +129,7 @@
             image.setMaxWidth(maxWidth);
         }
         final TextView name = (TextView) findViewById(R.id.widget_name);
-        name.setText(info.label);
+        name.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
         final TextView dims = (TextView) findViewById(R.id.widget_dims);
         if (dims != null) {
             int hSpan = Math.min(cellSpan[0], (int) grid.numColumns);
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
new file mode 100644
index 0000000..e191319
--- /dev/null
+++ b/src/com/android/launcher3/Partner.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.File;
+
+/**
+ * Utilities to discover and interact with partner customizations. There can
+ * only be one set of customizations on a device, and it must be bundled with
+ * the system.
+ */
+public class Partner {
+
+    static final String TAG = "Launcher.Partner";
+
+    /** Marker action used to discover partner */
+    private static final String
+            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
+
+    public static final String RES_FOLDER = "partner_folder";
+    public static final String RES_WALLPAPERS = "partner_wallpapers";
+    public static final String RES_DEFAULT_LAYOUT = "partner_default_layout";
+
+    public static final String RES_DEFAULT_WALLPAPER_HIDDEN = "default_wallpapper_hidden";
+    public static final String RES_SYSTEM_WALLPAPER_DIR = "system_wallpaper_directory";
+
+    public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
+
+    /** These resources are used to override the device profile  */
+    public static final String RES_GRID_AA_SHORT_EDGE_COUNT = "grid_aa_short_edge_count";
+    public static final String RES_GRID_AA_LONG_EDGE_COUNT = "grid_aa_long_edge_count";
+    public static final String RES_GRID_NUM_ROWS = "grid_num_rows";
+    public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
+    public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
+
+    private static boolean sSearched = false;
+    private static Partner sPartner;
+
+    /**
+     * Find and return partner details, or {@code null} if none exists.
+     */
+    public static synchronized Partner get(PackageManager pm) {
+        if (!sSearched) {
+            Pair<String, Resources> apkInfo = Utilities.findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm);
+            if (apkInfo != null) {
+                sPartner = new Partner(apkInfo.first, apkInfo.second);
+            }
+            sSearched = true;
+        }
+        return sPartner;
+    }
+
+    private final String mPackageName;
+    private final Resources mResources;
+
+    private Partner(String packageName, Resources res) {
+        mPackageName = packageName;
+        mResources = res;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public Resources getResources() {
+        return mResources;
+    }
+
+    public boolean hasDefaultLayout() {
+        int defaultLayout = getResources().getIdentifier(Partner.RES_DEFAULT_LAYOUT,
+                "xml", getPackageName());
+        return defaultLayout != 0;
+    }
+
+    public boolean hasFolder() {
+        int folder = getResources().getIdentifier(Partner.RES_FOLDER,
+                "xml", getPackageName());
+        return folder != 0;
+    }
+
+    public boolean hideDefaultWallpaper() {
+        int resId = getResources().getIdentifier(RES_DEFAULT_WALLPAPER_HIDDEN, "bool",
+                getPackageName());
+        return resId != 0 && getResources().getBoolean(resId);
+    }
+
+    public File getWallpaperDirectory() {
+        int resId = getResources().getIdentifier(RES_SYSTEM_WALLPAPER_DIR, "string",
+                getPackageName());
+        return (resId != 0) ? new File(getResources().getString(resId)) : null;
+    }
+
+    public boolean requiresFirstRunFlow() {
+        int resId = getResources().getIdentifier(RES_REQUIRE_FIRST_RUN_FLOW, "bool",
+                getPackageName());
+        return resId != 0 && getResources().getBoolean(resId);
+    }
+
+    public DeviceProfile getDeviceProfileOverride(DisplayMetrics dm) {
+        boolean containsProfileOverrides = false;
+
+        DeviceProfile dp = new DeviceProfile();
+
+        // We initialize customizable fields to be invalid
+        dp.numRows = -1;
+        dp.numColumns = -1;
+        dp.allAppsShortEdgeCount = -1;
+        dp.allAppsLongEdgeCount = -1;
+
+        try {
+            int resId = getResources().getIdentifier(RES_GRID_NUM_ROWS,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.numRows = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_NUM_COLUMNS,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.numColumns = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_AA_SHORT_EDGE_COUNT,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.allAppsShortEdgeCount = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_AA_LONG_EDGE_COUNT,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.allAppsLongEdgeCount = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_ICON_SIZE_DP,
+                    "dimen", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                int px = getResources().getDimensionPixelSize(resId);
+                dp.iconSize = DynamicGrid.dpiFromPx(px, dm);
+            }
+        } catch (Resources.NotFoundException ex) {
+            Log.e(TAG, "Invalid Partner grid resource!", ex);
+        }
+        return containsProfileOverrides ? dp : null;
+    }
+}
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
new file mode 100644
index 0000000..d23a330
--- /dev/null
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources.Theme;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener {
+
+    private static Theme sPreloaderTheme;
+
+    private final Rect mRect = new Rect();
+    private View mDefaultView;
+    private OnClickListener mClickListener;
+    private final LauncherAppWidgetInfo mInfo;
+    private final int mStartState;
+    private final Intent mIconLookupIntent;
+
+    private Bitmap mIcon;
+    private PreloadIconDrawable mDrawable;
+
+    private Drawable mCenterDrawable;
+    private Drawable mTopCornerDrawable;
+
+    private boolean mDrawableSizeChanged;
+
+    private final TextPaint mPaint;
+    private Layout mSetupTextLayout;
+
+    public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info) {
+        super(context);
+        mInfo = info;
+        mStartState = info.restoreStatus;
+        mIconLookupIntent = new Intent().setComponent(info.providerName);
+
+        mPaint = new TextPaint();
+        mPaint.setColor(0xFFFFFFFF);
+        mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
+                getDeviceProfile().iconTextSizePx, getResources().getDisplayMetrics()));
+        setBackgroundResource(R.drawable.quantum_panel_dark);
+        setWillNotDraw(false);
+    }
+
+    @Override
+    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
+            int maxHeight) {
+        // No-op
+    }
+
+    @Override
+    protected View getDefaultView() {
+        if (mDefaultView == null) {
+            mDefaultView = mInflater.inflate(R.layout.appwidget_not_ready, this, false);
+            mDefaultView.setOnClickListener(this);
+            applyState();
+        }
+        return mDefaultView;
+    }
+
+    @Override
+    public void setOnClickListener(OnClickListener l) {
+        mClickListener = l;
+    }
+
+    @Override
+    public boolean isReinflateRequired() {
+        // Re inflate is required any time the widget restore status changes
+        return mStartState != mInfo.restoreStatus;
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mDrawableSizeChanged = true;
+    }
+
+    public void updateIcon(IconCache cache) {
+        Bitmap icon = cache.getIcon(mIconLookupIntent, mInfo.user);
+        if (mIcon == icon) {
+            return;
+        }
+        mIcon = icon;
+        if (mDrawable != null) {
+            mDrawable.setCallback(null);
+            mDrawable = null;
+        }
+        if (mIcon != null) {
+            // The view displays two modes, one with a setup icon and another with a preload icon
+            // in the center.
+            if (isReadyForClickSetup()) {
+                mCenterDrawable = getResources().getDrawable(R.drawable.ic_setting);
+                mTopCornerDrawable = new FastBitmapDrawable(mIcon);
+            } else {
+                if (sPreloaderTheme == null) {
+                    sPreloaderTheme = getResources().newTheme();
+                    sPreloaderTheme.applyStyle(R.style.PreloadIcon, true);
+                }
+
+                FastBitmapDrawable drawable = Utilities.createIconDrawable(mIcon);
+                mDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
+                mDrawable.setCallback(this);
+                applyState();
+            }
+            mDrawableSizeChanged = true;
+        }
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return (who == mDrawable) || super.verifyDrawable(who);
+    }
+
+    public void applyState() {
+        if (mDrawable != null) {
+            mDrawable.setLevel(Math.max(mInfo.installProgress, 0));
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        // AppWidgetHostView blocks all click events on the root view. Instead handle click events
+        // on the content and pass it along.
+        if (mClickListener != null) {
+            mClickListener.onClick(this);
+        }
+    }
+
+    public boolean isReadyForClickSetup() {
+        return (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0
+                && (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mDrawable != null) {
+            if (mDrawableSizeChanged) {
+                int maxSize = LauncherAppState.getInstance().getDynamicGrid()
+                        .getDeviceProfile().iconSizePx + 2 * mDrawable.getOutset();
+                int size = Math.min(maxSize, Math.min(
+                        getWidth() - getPaddingLeft() - getPaddingRight(),
+                        getHeight() - getPaddingTop() - getPaddingBottom()));
+
+                mRect.set(0, 0, size, size);
+                mRect.inset(mDrawable.getOutset(), mDrawable.getOutset());
+                mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
+                mDrawable.setBounds(mRect);
+                mDrawableSizeChanged = false;
+            }
+
+            mDrawable.draw(canvas);
+        } else if ((mCenterDrawable != null) && (mTopCornerDrawable != null)) {
+            if (mDrawableSizeChanged) {
+                DeviceProfile grid = getDeviceProfile();
+                int iconSize = grid.iconSizePx;
+                int paddingTop = getPaddingTop();
+                int paddingBottom = getPaddingBottom();
+                int paddingLeft = getPaddingLeft();
+                int paddingRight = getPaddingRight();
+
+                int availableWidth = getWidth() - paddingLeft - paddingRight;
+                int availableHeight = getHeight() - paddingTop - paddingBottom;
+
+                // Recreate the setup text.
+                mSetupTextLayout = new StaticLayout(
+                        getResources().getText(R.string.gadget_setup_text), mPaint, availableWidth,
+                        Layout.Alignment.ALIGN_CENTER, 1, 0, true);
+                if (mSetupTextLayout.getLineCount() == 1) {
+                    // The text fits in a single line. No need to draw the setup icon.
+                    int size = Math.min(iconSize, Math.min(availableWidth,
+                            availableHeight - mSetupTextLayout.getHeight()));
+                    mRect.set(0, 0, size, size);
+                    mRect.offsetTo((getWidth() - mRect.width()) / 2,
+                            (getHeight() - mRect.height() - mSetupTextLayout.getHeight()
+                                    - grid.iconDrawablePaddingPx) / 2);
+
+                    mTopCornerDrawable.setBounds(mRect);
+
+                    // Update left and top to indicate the position where the text will be drawn.
+                    mRect.left = paddingLeft;
+                    mRect.top = mRect.bottom + grid.iconDrawablePaddingPx;
+                } else {
+                    // The text can't be drawn in a single line. Draw a setup icon instead.
+                    mSetupTextLayout = null;
+                    int size = Math.min(iconSize, Math.min(
+                            getWidth() - paddingLeft - paddingRight,
+                            getHeight() - paddingTop - paddingBottom));
+                    mRect.set(0, 0, size, size);
+                    mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
+                    mCenterDrawable.setBounds(mRect);
+
+                    size = Math.min(size / 2,
+                            Math.max(mRect.top - paddingTop, mRect.left - paddingLeft));
+                    mTopCornerDrawable.setBounds(paddingLeft, paddingTop,
+                            paddingLeft + size, paddingTop + size);
+                }
+                mDrawableSizeChanged = false;
+            }
+
+            if (mSetupTextLayout == null) {
+                mCenterDrawable.draw(canvas);
+                mTopCornerDrawable.draw(canvas);
+            } else {
+                canvas.save();
+                canvas.translate(mRect.left, mRect.top);
+                mSetupTextLayout.draw(canvas);
+                canvas.restore();
+                mTopCornerDrawable.draw(canvas);
+            }
+        }
+    }
+
+    private DeviceProfile getDeviceProfile() {
+        return LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
+    }
+}
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
new file mode 100644
index 0000000..2972c4f
--- /dev/null
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -0,0 +1,249 @@
+package com.android.launcher3;
+
+import android.animation.ObjectAnimator;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+class PreloadIconDrawable extends Drawable {
+
+    private static final float ANIMATION_PROGRESS_STOPPED = -1.0f;
+    private static final float ANIMATION_PROGRESS_STARTED = 0f;
+    private static final float ANIMATION_PROGRESS_COMPLETED = 1.0f;
+
+    private static final float MIN_SATUNATION = 0.2f;
+    private static final float MIN_LIGHTNESS = 0.6f;
+
+    private static final float ICON_SCALE_FACTOR = 0.5f;
+    private static final int DEFAULT_COLOR = 0xFF009688;
+
+    private static final Rect sTempRect = new Rect();
+
+    private final RectF mIndicatorRect = new RectF();
+    private boolean mIndicatorRectDirty;
+
+    private final Paint mPaint;
+    final Drawable mIcon;
+
+    private Drawable mBgDrawable;
+    private int mRingOutset;
+
+    private int mIndicatorColor = 0;
+
+    /**
+     * Indicates the progress of the preloader [0-100]. If it goes above 100, only the icon
+     * is shown with no progress bar.
+     */
+    private int mProgress = 0;
+
+    private float mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+    private ObjectAnimator mAnimator;
+
+    public PreloadIconDrawable(Drawable icon, Theme theme) {
+        mIcon = icon;
+
+        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeCap(Paint.Cap.ROUND);
+
+        setBounds(icon.getBounds());
+        applyTheme(theme);
+        onLevelChange(0);
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        TypedArray ta = t.obtainStyledAttributes(R.styleable.PreloadIconDrawable);
+        mBgDrawable = ta.getDrawable(R.styleable.PreloadIconDrawable_background);
+        mBgDrawable.setFilterBitmap(true);
+        mPaint.setStrokeWidth(ta.getDimension(R.styleable.PreloadIconDrawable_indicatorSize, 0));
+        mRingOutset = ta.getDimensionPixelSize(R.styleable.PreloadIconDrawable_ringOutset, 0);
+        ta.recycle();
+        onBoundsChange(getBounds());
+        invalidateSelf();
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        mIcon.setBounds(bounds);
+        if (mBgDrawable != null) {
+            sTempRect.set(bounds);
+            sTempRect.inset(-mRingOutset, -mRingOutset);
+            mBgDrawable.setBounds(sTempRect);
+        }
+        mIndicatorRectDirty = true;
+    }
+
+    public int getOutset() {
+        return mRingOutset;
+    }
+
+    /**
+     * The size of the indicator is same as the content region of the {@link #mBgDrawable} minus
+     * half the stroke size to accommodate the indicator.
+     */
+    private void initIndicatorRect() {
+        Drawable d = mBgDrawable;
+        Rect bounds = d.getBounds();
+
+        d.getPadding(sTempRect);
+        // Amount by which padding has to be scaled
+        float paddingScaleX = ((float) bounds.width()) / d.getIntrinsicWidth();
+        float paddingScaleY = ((float) bounds.height()) / d.getIntrinsicHeight();
+        mIndicatorRect.set(
+                bounds.left + sTempRect.left * paddingScaleX,
+                bounds.top + sTempRect.top * paddingScaleY,
+                bounds.right - sTempRect.right * paddingScaleX,
+                bounds.bottom - sTempRect.bottom * paddingScaleY);
+
+        float inset = mPaint.getStrokeWidth() / 2;
+        mIndicatorRect.inset(inset, inset);
+        mIndicatorRectDirty = false;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final Rect r = new Rect(getBounds());
+        if (canvas.getClipBounds(sTempRect) && !Rect.intersects(sTempRect, r)) {
+            // The draw region has been clipped.
+            return;
+        }
+        if (mIndicatorRectDirty) {
+            initIndicatorRect();
+        }
+        final float iconScale;
+
+        if ((mAnimationProgress >= ANIMATION_PROGRESS_STARTED)
+                && (mAnimationProgress < ANIMATION_PROGRESS_COMPLETED)) {
+            mPaint.setAlpha((int) ((1 - mAnimationProgress) * 255));
+            mBgDrawable.setAlpha(mPaint.getAlpha());
+            mBgDrawable.draw(canvas);
+            canvas.drawOval(mIndicatorRect, mPaint);
+
+            iconScale = ICON_SCALE_FACTOR + (1 - ICON_SCALE_FACTOR) * mAnimationProgress;
+        } else if (mAnimationProgress == ANIMATION_PROGRESS_STOPPED) {
+            mPaint.setAlpha(255);
+            iconScale = ICON_SCALE_FACTOR;
+            mBgDrawable.setAlpha(255);
+            mBgDrawable.draw(canvas);
+
+            if (mProgress >= 100) {
+                canvas.drawOval(mIndicatorRect, mPaint);
+            } else if (mProgress > 0) {
+                canvas.drawArc(mIndicatorRect, -90, mProgress * 3.6f, false, mPaint);
+            }
+        } else {
+            iconScale = 1;
+        }
+
+        canvas.save();
+        canvas.scale(iconScale, iconScale, r.exactCenterX(), r.exactCenterY());
+        mIcon.draw(canvas);
+        canvas.restore();
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mIcon.setAlpha(alpha);
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        mIcon.setColorFilter(cf);
+    }
+
+    @Override
+    protected boolean onLevelChange(int level) {
+        mProgress = level;
+
+        // Stop Animation
+        if (mAnimator != null) {
+            mAnimator.cancel();
+            mAnimator = null;
+        }
+        mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+        if (level > 0) {
+            // Set the paint color only when the level changes, so that the dominant color
+            // is only calculated when needed.
+            mPaint.setColor(getIndicatorColor());
+        }
+        if (mIcon instanceof FastBitmapDrawable) {
+            ((FastBitmapDrawable) mIcon).setGhostModeEnabled(level <= 0);
+        }
+
+        invalidateSelf();
+        return true;
+    }
+
+    /**
+     * Runs the finish animation if it is has not been run after last level change.
+     */
+    public void maybePerformFinishedAnimation() {
+        if (mAnimationProgress > ANIMATION_PROGRESS_STOPPED) {
+            return;
+        }
+        if (mAnimator != null) {
+            mAnimator.cancel();
+        }
+        setAnimationProgress(ANIMATION_PROGRESS_STARTED);
+        mAnimator = ObjectAnimator.ofFloat(this, "animationProgress",
+                ANIMATION_PROGRESS_STARTED, ANIMATION_PROGRESS_COMPLETED);
+        mAnimator.start();
+    }
+
+    public void setAnimationProgress(float progress) {
+        if (progress != mAnimationProgress) {
+            mAnimationProgress = progress;
+            invalidateSelf();
+        }
+    }
+
+    public float getAnimationProgress() {
+        return mAnimationProgress;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mIcon.getIntrinsicHeight();
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mIcon.getIntrinsicWidth();
+    }
+
+    private int getIndicatorColor() {
+        if (mIndicatorColor != 0) {
+            return mIndicatorColor;
+        }
+        if (!(mIcon instanceof FastBitmapDrawable)) {
+            mIndicatorColor = DEFAULT_COLOR;
+            return mIndicatorColor;
+        }
+        mIndicatorColor = Utilities.findDominantColorByHue(
+                ((FastBitmapDrawable) mIcon).getBitmap(), 20);
+
+        // Make sure that the dominant color has enough saturation to be visible properly.
+        float[] hsv = new float[3];
+        Color.colorToHSV(mIndicatorColor, hsv);
+        if (hsv[1] < MIN_SATUNATION) {
+            mIndicatorColor = DEFAULT_COLOR;
+            return mIndicatorColor;
+        }
+        hsv[2] = Math.max(MIN_LIGHTNESS, hsv[2]);
+        mIndicatorColor = Color.HSVToColor(hsv);
+        return mIndicatorColor;
+    }
+}
diff --git a/src/com/android/launcher3/PreloadReceiver.java b/src/com/android/launcher3/PreloadReceiver.java
deleted file mode 100644
index ca25746..0000000
--- a/src/com/android/launcher3/PreloadReceiver.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.text.TextUtils;
-import android.util.Log;
-
-public class PreloadReceiver extends BroadcastReceiver {
-    private static final String TAG = "Launcher.PreloadReceiver";
-    private static final boolean LOGD = false;
-
-    public static final String EXTRA_WORKSPACE_NAME =
-            "com.android.launcher3.action.EXTRA_WORKSPACE_NAME";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final LauncherProvider provider = LauncherAppState.getLauncherProvider();
-        if (provider != null) {
-            String name = intent.getStringExtra(EXTRA_WORKSPACE_NAME);
-            final int workspaceResId = !TextUtils.isEmpty(name)
-                    ? context.getResources().getIdentifier(name, "xml", "com.android.launcher3") : 0;
-            if (LOGD) {
-                Log.d(TAG, "workspace name: " + name + " id: " + workspaceResId);
-            }
-            new AsyncTask<Void, Void, Void>() {
-                public Void doInBackground(Void ... args) {
-                    provider.loadDefaultFavoritesIfNecessary(workspaceResId);
-                    return null;
-                }
-            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
-        }
-    }
-}
diff --git a/src/com/android/launcher3/ScrimView.java b/src/com/android/launcher3/ScrimView.java
deleted file mode 100644
index 68200fe..0000000
--- a/src/com/android/launcher3/ScrimView.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-public class ScrimView extends FrameLayout implements Insettable {
-
-    public ScrimView(Context context) {
-        this(context, null, 0);
-    }
-
-    public ScrimView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public ScrimView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    public void setInsets(Rect insets) {
-        // Do nothing
-    }
-}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 660f32c..daf3434 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -20,18 +20,44 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.util.Log;
 
+import com.android.launcher3.compat.UserHandleCompat;
+
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Represents a launchable icon on the workspaces and in folders.
  */
-class ShortcutInfo extends ItemInfo {
+public class ShortcutInfo extends ItemInfo {
+
+    public static final int DEFAULT = 0;
+
+    /**
+     * The shortcut was restored from a backup and it not ready to be used. This is automatically
+     * set during backup/restore
+     */
+    public static final int FLAG_RESTORED_ICON = 1;
+
+    /**
+     * The icon was added as an auto-install app, and is not ready to be used. This flag can't
+     * be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout
+     * parsing.
+     */
+    public static final int FLAG_AUTOINTALL_ICON = 2;
+
+    /**
+     * The icon is being installed. If {@link FLAG_RESTORED_ICON} or {@link FLAG_AUTOINTALL_ICON}
+     * is set, then the icon is either being installed or is in a broken state.
+     */
+    public static final int FLAG_INSTALL_SESSION_ACTIVE = 4;
+
+    /**
+     * Indicates that the widget restore has started.
+     */
+    public static final int FLAG_RESTORE_STARTED = 8;
 
     /**
      * The intent used to start the application.
@@ -61,22 +87,52 @@
      */
     private Bitmap mIcon;
 
+    /**
+     * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when
+     * sd-card is not available).
+     */
+    boolean isDisabled = false;
+
+    int status;
+
+    /**
+     * The installation progress [0-100] of the package that this shortcut represents.
+     */
+    private int mInstallProgress;
+
+    /**
+     * Refer {@link AppInfo#firstInstallTime}.
+     */
     long firstInstallTime;
+
+    /**
+     * TODO move this to {@link status}
+     */
     int flags = 0;
 
+    /**
+     * If this shortcut is a placeholder, then intent will be a market intent for the package, and
+     * this will hold the original intent from the database.  Otherwise, null.
+     * Refer {@link #FLAG_RESTORE_PENDING}, {@link #FLAG_INSTALL_PENDING}
+     */
+    Intent promisedIntent;
+
     ShortcutInfo() {
         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
     }
 
-    protected Intent getIntent() {
+    public Intent getIntent() {
         return intent;
     }
 
-    ShortcutInfo(Intent intent, CharSequence title, Bitmap icon) {
+    ShortcutInfo(Intent intent, CharSequence title, CharSequence contentDescription,
+            Bitmap icon, UserHandleCompat user) {
         this();
         this.intent = intent;
         this.title = title;
+        this.contentDescription = contentDescription;
         mIcon = icon;
+        this.user = user;
     }
 
     public ShortcutInfo(Context context, ShortcutInfo info) {
@@ -90,8 +146,10 @@
         }
         mIcon = info.mIcon; // TODO: should make a copy here.  maybe we don't need this ctor at all
         customIcon = info.customIcon;
-        initFlagsAndFirstInstallTime(
-                getPackageInfo(context, intent.getComponent().getPackageName()));
+        flags = info.flags;
+        firstInstallTime = info.firstInstallTime;
+        user = info.user;
+        status = info.status;
     }
 
     /** TODO: Remove this.  It's only called by ApplicationInfo.makeShortcut. */
@@ -104,22 +162,6 @@
         firstInstallTime = info.firstInstallTime;
     }
 
-    public static PackageInfo getPackageInfo(Context context, String packageName) {
-        PackageInfo pi = null;
-        try {
-            PackageManager pm = context.getPackageManager();
-            pi = pm.getPackageInfo(packageName, 0);
-        } catch (NameNotFoundException e) {
-            Log.d("ShortcutInfo", "PackageManager.getPackageInfo failed for " + packageName);
-        }
-        return pi;
-    }
-
-    void initFlagsAndFirstInstallTime(PackageInfo pi) {
-        flags = AppInfo.initFlags(pi);
-        firstInstallTime = AppInfo.initFirstInstallTime(pi);
-    }
-
     public void setIcon(Bitmap b) {
         mIcon = b;
     }
@@ -132,35 +174,19 @@
     }
 
     public void updateIcon(IconCache iconCache) {
-        mIcon = iconCache.getIcon(intent);
-        usingFallbackIcon = iconCache.isDefaultIcon(mIcon);
-    }
-
-    /**
-     * Creates the application intent based on a component name and various launch flags.
-     * Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
-     *
-     * @param className the class name of the component representing the intent
-     * @param launchFlags the launch flags
-     */
-    final void setActivity(Context context, ComponentName className, int launchFlags) {
-        intent = new Intent(Intent.ACTION_MAIN);
-        intent.addCategory(Intent.CATEGORY_LAUNCHER);
-        intent.setComponent(className);
-        intent.setFlags(launchFlags);
-        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
-        initFlagsAndFirstInstallTime(
-                getPackageInfo(context, intent.getComponent().getPackageName()));
+        mIcon = iconCache.getIcon(promisedIntent != null ? promisedIntent : intent, user);
+        usingFallbackIcon = iconCache.isDefaultIcon(mIcon, user);
     }
 
     @Override
-    void onAddToDatabase(ContentValues values) {
-        super.onAddToDatabase(values);
+    void onAddToDatabase(Context context, ContentValues values) {
+        super.onAddToDatabase(context, values);
 
         String titleStr = title != null ? title.toString() : null;
         values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
 
-        String uri = intent != null ? intent.toUri(0) : null;
+        String uri = promisedIntent != null ? promisedIntent.toUri(0)
+                : (intent != null ? intent.toUri(0) : null);
         values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
 
         if (customIcon) {
@@ -184,10 +210,10 @@
 
     @Override
     public String toString() {
-        return "ShortcutInfo(title=" + title.toString() + "intent=" + intent + "id=" + this.id
+        return "ShortcutInfo(title=" + title + "intent=" + intent + "id=" + this.id
                 + " type=" + this.itemType + " container=" + this.container + " screen=" + screenId
                 + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY
-                + " dropPos=" + dropPos + ")";
+                + " dropPos=" + Arrays.toString(dropPos) + " user=" + user + ")";
     }
 
     public static void dumpShortcutInfoList(String tag, String label,
@@ -198,5 +224,27 @@
                     + " customIcon=" + info.customIcon);
         }
     }
+
+    public ComponentName getTargetComponent() {
+        return promisedIntent != null ? promisedIntent.getComponent() : intent.getComponent();
+    }
+
+    public boolean hasStatusFlag(int flag) {
+        return (status & flag) != 0;
+    }
+
+
+    public final boolean isPromise() {
+        return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON);
+    }
+
+    public int getInstallProgress() {
+        return mInstallProgress;
+    }
+
+    public void setInstallProgress(int progress) {
+        mInstallProgress = progress;
+        status |= FLAG_INSTALL_SESSION_ACTIVE;
+    }
 }
 
diff --git a/src/com/android/launcher3/StartupReceiver.java b/src/com/android/launcher3/StartupReceiver.java
new file mode 100644
index 0000000..65f913f
--- /dev/null
+++ b/src/com/android/launcher3/StartupReceiver.java
@@ -0,0 +1,15 @@
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class StartupReceiver extends BroadcastReceiver {
+
+    static final String SYSTEM_READY = "com.android.launcher3.SYSTEM_READY";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        context.sendStickyBroadcast(new Intent(SYSTEM_READY));
+    }
+}
diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java
index 882fb04..f3977e4 100644
--- a/src/com/android/launcher3/Stats.java
+++ b/src/com/android/launcher3/Stats.java
@@ -32,7 +32,6 @@
     private static final boolean LOCAL_LAUNCH_LOG = true;
 
     public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
-    public static final String PERM_LAUNCH = "com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS";
     public static final String EXTRA_INTENT = "intent";
     public static final String EXTRA_CONTAINER = "container";
     public static final String EXTRA_SCREEN = "screen";
@@ -53,6 +52,8 @@
 
     private final Launcher mLauncher;
 
+    private final String mLaunchBroadcastPermission;
+
     DataOutputStream mLog;
 
     ArrayList<String> mIntents;
@@ -61,6 +62,9 @@
     public Stats(Launcher launcher) {
         mLauncher = launcher;
 
+        mLaunchBroadcastPermission =
+                launcher.getResources().getString(R.string.receive_launch_broadcasts_permission);
+
         loadStats();
 
         if (LOCAL_LAUNCH_LOG) {
@@ -87,7 +91,7 @@
                         }
                     },
                     new IntentFilter(ACTION_LAUNCH),
-                    PERM_LAUNCH,
+                    mLaunchBroadcastPermission,
                     null
             );
         }
@@ -120,7 +124,7 @@
                     .putExtra(EXTRA_CELLX, shortcut.cellX)
                     .putExtra(EXTRA_CELLY, shortcut.cellY);
         }
-        mLauncher.sendBroadcast(broadcastIntent, PERM_LAUNCH);
+        mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
 
         incrementLaunch(flat);
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index cbc9785..80d4b22 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -18,14 +18,18 @@
 
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
@@ -33,8 +37,10 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
-import android.util.DisplayMetrics;
+import android.os.Build;
 import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
 import android.view.View;
 import android.widget.Toast;
 
@@ -51,10 +57,6 @@
     public static int sIconTextureWidth = -1;
     public static int sIconTextureHeight = -1;
 
-    private static final Paint sBlurPaint = new Paint();
-    private static final Paint sGlowColorPressedPaint = new Paint();
-    private static final Paint sGlowColorFocusedPaint = new Paint();
-    private static final Paint sDisabledPaint = new Paint();
     private static final Rect sOldBounds = new Rect();
     private static final Canvas sCanvas = new Canvas();
 
@@ -65,6 +67,8 @@
     static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
     static int sColorIndex = 0;
 
+    static int[] sLoc0 = new int[2];
+    static int[] sLoc1 = new int[2];
 
     // To turn on these properties, type
     // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
@@ -74,7 +78,7 @@
     /**
      * Returns a FastBitmapDrawable with the icon, accurately sized.
      */
-    static Drawable createIconDrawable(Bitmap icon) {
+    public static FastBitmapDrawable createIconDrawable(Bitmap icon) {
         FastBitmapDrawable d = new FastBitmapDrawable(icon);
         d.setFilterBitmap(true);
         resizeIconDrawable(d);
@@ -99,6 +103,13 @@
     }
 
     /**
+     * Indicates if the device is running LMP or higher.
+     */
+    public static boolean isLmpOrAbove() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.L;
+    }
+
+    /**
      * Returns a bitmap suitable for the all apps view. Used to convert pre-ICS
      * icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size)
      * to the proper size (48dp)
@@ -305,22 +316,21 @@
         return scale;
     }
 
+    /**
+     * Utility method to determine whether the given point, in local coordinates,
+     * is inside the view, where the area of the view is expanded by the slop factor.
+     * This method is called while processing touch-move events to determine if the event
+     * is still within the view.
+     */
+    public static boolean pointInView(View v, float localX, float localY, float slop) {
+        return localX >= -slop && localY >= -slop && localX < (v.getWidth() + slop) &&
+                localY < (v.getHeight() + slop);
+    }
+
     private static void initStatics(Context context) {
         final Resources resources = context.getResources();
-        final DisplayMetrics metrics = resources.getDisplayMetrics();
-        final float density = metrics.density;
-
         sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
         sIconTextureWidth = sIconTextureHeight = sIconWidth;
-
-        sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
-        sGlowColorPressedPaint.setColor(0xffffc300);
-        sGlowColorFocusedPaint.setColor(0xffff8e00);
-
-        ColorMatrix cm = new ColorMatrix();
-        cm.setSaturation(0.2f);
-        sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm));
-        sDisabledPaint.setAlpha(0x88);
     }
 
     public static void setIconSize(int widthPx) {
@@ -337,6 +347,25 @@
         }
     }
 
+    public static int[] getCenterDeltaInScreenSpace(View v0, View v1, int[] delta) {
+        v0.getLocationInWindow(sLoc0);
+        v1.getLocationInWindow(sLoc1);
+
+        sLoc0[0] += (v0.getMeasuredWidth() * v0.getScaleX()) / 2;
+        sLoc0[1] += (v0.getMeasuredHeight() * v0.getScaleY()) / 2;
+        sLoc1[0] += (v1.getMeasuredWidth() * v1.getScaleX()) / 2;
+        sLoc1[1] += (v1.getMeasuredHeight() * v1.getScaleY()) / 2;
+
+        if (delta == null) {
+            delta = new int[2];
+        }
+
+        delta[0] = sLoc1[0] - sLoc0[0];
+        delta[1] = sLoc1[1] - sLoc0[1];
+
+        return delta;
+    }
+
     public static void scaleRectAboutCenter(Rect r, float scale) {
         int cx = r.centerX();
         int cy = r.centerY();
@@ -358,4 +387,130 @@
                     "or use the exported attribute for this activity.", e);
         }
     }
+
+    static boolean isSystemApp(Context context, Intent intent) {
+        PackageManager pm = context.getPackageManager();
+        ComponentName cn = intent.getComponent();
+        String packageName = null;
+        if (cn == null) {
+            ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+            if ((info != null) && (info.activityInfo != null)) {
+                packageName = info.activityInfo.packageName;
+            }
+        } else {
+            packageName = cn.getPackageName();
+        }
+        if (packageName != null) {
+            try {
+                PackageInfo info = pm.getPackageInfo(packageName, 0);
+                return (info != null) && (info.applicationInfo != null) &&
+                        ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+            } catch (NameNotFoundException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * This picks a dominant color, looking for high-saturation, high-value, repeated hues.
+     * @param bitmap The bitmap to scan
+     * @param samples The approximate max number of samples to use.
+     */
+    static int findDominantColorByHue(Bitmap bitmap, int samples) {
+        final int height = bitmap.getHeight();
+        final int width = bitmap.getWidth();
+        int sampleStride = (int) Math.sqrt((height * width) / samples);
+        if (sampleStride < 1) {
+            sampleStride = 1;
+        }
+
+        // This is an out-param, for getting the hsv values for an rgb
+        float[] hsv = new float[3];
+
+        // First get the best hue, by creating a histogram over 360 hue buckets,
+        // where each pixel contributes a score weighted by saturation, value, and alpha.
+        float[] hueScoreHistogram = new float[360];
+        float highScore = -1;
+        int bestHue = -1;
+
+        for (int y = 0; y < height; y += sampleStride) {
+            for (int x = 0; x < width; x += sampleStride) {
+                int argb = bitmap.getPixel(x, y);
+                int alpha = 0xFF & (argb >> 24);
+                if (alpha < 0x80) {
+                    // Drop mostly-transparent pixels.
+                    continue;
+                }
+                // Remove the alpha channel.
+                int rgb = argb | 0xFF000000;
+                Color.colorToHSV(rgb, hsv);
+                // Bucket colors by the 360 integer hues.
+                int hue = (int) hsv[0];
+                if (hue < 0 || hue >= hueScoreHistogram.length) {
+                    // Defensively avoid array bounds violations.
+                    continue;
+                }
+                float score = hsv[1] * hsv[2];
+                hueScoreHistogram[hue] += score;
+                if (hueScoreHistogram[hue] > highScore) {
+                    highScore = hueScoreHistogram[hue];
+                    bestHue = hue;
+                }
+            }
+        }
+
+        SparseArray<Float> rgbScores = new SparseArray<Float>();
+        int bestColor = 0xff000000;
+        highScore = -1;
+        // Go back over the RGB colors that match the winning hue,
+        // creating a histogram of weighted s*v scores, for up to 100*100 [s,v] buckets.
+        // The highest-scoring RGB color wins.
+        for (int y = 0; y < height; y += sampleStride) {
+            for (int x = 0; x < width; x += sampleStride) {
+                int rgb = bitmap.getPixel(x, y) | 0xff000000;
+                Color.colorToHSV(rgb, hsv);
+                int hue = (int) hsv[0];
+                if (hue == bestHue) {
+                    float s = hsv[1];
+                    float v = hsv[2];
+                    int bucket = (int) (s * 100) + (int) (v * 10000);
+                    // Score by cumulative saturation * value.
+                    float score = s * v;
+                    Float oldTotal = rgbScores.get(bucket);
+                    float newTotal = oldTotal == null ? score : oldTotal + score;
+                    rgbScores.put(bucket, newTotal);
+                    if (newTotal > highScore) {
+                        highScore = newTotal;
+                        // All the colors in the winning bucket are very similar. Last in wins.
+                        bestColor = rgb;
+                    }
+                }
+            }
+        }
+        return bestColor;
+    }
+
+    /*
+     * Finds a system apk which had a broadcast receiver listening to a particular action.
+     * @param action intent action used to find the apk
+     * @return a pair of apk package name and the resources.
+     */
+    static Pair<String, Resources> findSystemApk(String action, PackageManager pm) {
+        final Intent intent = new Intent(action);
+        for (ResolveInfo info : pm.queryBroadcastReceivers(intent, 0)) {
+            if (info.activityInfo != null &&
+                    (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                final String packageName = info.activityInfo.packageName;
+                try {
+                    final Resources res = pm.getResourcesForApplication(packageName);
+                    return Pair.create(packageName, res);
+                } catch (NameNotFoundException e) {
+                    Log.w(TAG, "Failed to find resources for " + packageName);
+                }
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/launcher3/WidgetAdder.java b/src/com/android/launcher3/WidgetAdder.java
deleted file mode 100644
index 79ac504..0000000
--- a/src/com/android/launcher3/WidgetAdder.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.android.launcher3;
-
-import android.app.Activity;
-
-public class WidgetAdder extends Activity {
-
-}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 7e1ad6d..5aa7190 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -5,15 +5,17 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteCantOpenDatabaseException;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDiskIOException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
@@ -26,129 +28,138 @@
 import android.os.AsyncTask;
 import android.util.Log;
 
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.IOException;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
-
-abstract class SoftReferenceThreadLocal<T> {
-    private ThreadLocal<SoftReference<T>> mThreadLocal;
-    public SoftReferenceThreadLocal() {
-        mThreadLocal = new ThreadLocal<SoftReference<T>>();
-    }
-
-    abstract T initialValue();
-
-    public void set(T t) {
-        mThreadLocal.set(new SoftReference<T>(t));
-    }
-
-    public T get() {
-        SoftReference<T> reference = mThreadLocal.get();
-        T obj;
-        if (reference == null) {
-            obj = initialValue();
-            mThreadLocal.set(new SoftReference<T>(obj));
-            return obj;
-        } else {
-            obj = reference.get();
-            if (obj == null) {
-                obj = initialValue();
-                mThreadLocal.set(new SoftReference<T>(obj));
-            }
-            return obj;
-        }
-    }
-}
-
-class CanvasCache extends SoftReferenceThreadLocal<Canvas> {
-    @Override
-    protected Canvas initialValue() {
-        return new Canvas();
-    }
-}
-
-class PaintCache extends SoftReferenceThreadLocal<Paint> {
-    @Override
-    protected Paint initialValue() {
-        return null;
-    }
-}
-
-class BitmapCache extends SoftReferenceThreadLocal<Bitmap> {
-    @Override
-    protected Bitmap initialValue() {
-        return null;
-    }
-}
-
-class RectCache extends SoftReferenceThreadLocal<Rect> {
-    @Override
-    protected Rect initialValue() {
-        return new Rect();
-    }
-}
-
-class BitmapFactoryOptionsCache extends SoftReferenceThreadLocal<BitmapFactory.Options> {
-    @Override
-    protected BitmapFactory.Options initialValue() {
-        return new BitmapFactory.Options();
-    }
-}
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 
 public class WidgetPreviewLoader {
-    static final String TAG = "WidgetPreviewLoader";
-    static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
+
+    private static abstract class SoftReferenceThreadLocal<T> {
+        private ThreadLocal<SoftReference<T>> mThreadLocal;
+        public SoftReferenceThreadLocal() {
+            mThreadLocal = new ThreadLocal<SoftReference<T>>();
+        }
+
+        abstract T initialValue();
+
+        public void set(T t) {
+            mThreadLocal.set(new SoftReference<T>(t));
+        }
+
+        public T get() {
+            SoftReference<T> reference = mThreadLocal.get();
+            T obj;
+            if (reference == null) {
+                obj = initialValue();
+                mThreadLocal.set(new SoftReference<T>(obj));
+                return obj;
+            } else {
+                obj = reference.get();
+                if (obj == null) {
+                    obj = initialValue();
+                    mThreadLocal.set(new SoftReference<T>(obj));
+                }
+                return obj;
+            }
+        }
+    }
+
+    private static class CanvasCache extends SoftReferenceThreadLocal<Canvas> {
+        @Override
+        protected Canvas initialValue() {
+            return new Canvas();
+        }
+    }
+
+    private static class PaintCache extends SoftReferenceThreadLocal<Paint> {
+        @Override
+        protected Paint initialValue() {
+            return null;
+        }
+    }
+
+    private static class BitmapCache extends SoftReferenceThreadLocal<Bitmap> {
+        @Override
+        protected Bitmap initialValue() {
+            return null;
+        }
+    }
+
+    private static class RectCache extends SoftReferenceThreadLocal<Rect> {
+        @Override
+        protected Rect initialValue() {
+            return new Rect();
+        }
+    }
+
+    private static class BitmapFactoryOptionsCache extends
+            SoftReferenceThreadLocal<BitmapFactory.Options> {
+        @Override
+        protected BitmapFactory.Options initialValue() {
+            return new BitmapFactory.Options();
+        }
+    }
+
+    private static final String TAG = "WidgetPreviewLoader";
+    private static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
+
+    private static final float WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE = 0.25f;
+    private static final HashSet<String> sInvalidPackages = new HashSet<String>();
+
+    // Used for drawing shortcut previews
+    private final BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
+    private final PaintCache mCachedShortcutPreviewPaint = new PaintCache();
+    private final CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
+
+    // Used for drawing widget previews
+    private final CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
+    private final RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
+    private final RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
+    private final PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
+    private final PaintCache mDefaultAppWidgetPreviewPaint = new PaintCache();
+    private final BitmapFactoryOptionsCache mCachedBitmapFactoryOptions = new BitmapFactoryOptionsCache();
+
+    private final HashMap<String, WeakReference<Bitmap>> mLoadedPreviews = new HashMap<>();
+    private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps = new ArrayList<>();
+
+    private final Context mContext;
+    private final int mAppIconSize;
+    private final IconCache mIconCache;
+    private final AppWidgetManagerCompat mManager;
 
     private int mPreviewBitmapWidth;
     private int mPreviewBitmapHeight;
     private String mSize;
-    private Context mContext;
-    private PackageManager mPackageManager;
     private PagedViewCellLayout mWidgetSpacingLayout;
 
-    // Used for drawing shortcut previews
-    private BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
-    private PaintCache mCachedShortcutPreviewPaint = new PaintCache();
-    private CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
-
-    // Used for drawing widget previews
-    private CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
-    private RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
-    private RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
-    private PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
     private String mCachedSelectQuery;
-    private BitmapFactoryOptionsCache mCachedBitmapFactoryOptions = new BitmapFactoryOptionsCache();
 
-    private int mAppIconSize;
-    private IconCache mIconCache;
-
-    private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
 
     private CacheDb mDb;
 
-    private HashMap<String, WeakReference<Bitmap>> mLoadedPreviews;
-    private ArrayList<SoftReference<Bitmap>> mUnusedBitmaps;
-    private static HashSet<String> sInvalidPackages;
-
-    static {
-        sInvalidPackages = new HashSet<String>();
-    }
+    private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
 
     public WidgetPreviewLoader(Context context) {
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
 
         mContext = context;
-        mPackageManager = mContext.getPackageManager();
         mAppIconSize = grid.iconSizePx;
         mIconCache = app.getIconCache();
+        mManager = AppWidgetManagerCompat.getInstance(context);
+
         mDb = app.getWidgetPreviewCacheDb();
-        mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>();
-        mUnusedBitmaps = new ArrayList<SoftReference<Bitmap>>();
 
         SharedPreferences sp = context.getSharedPreferences(
                 LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
@@ -165,6 +176,12 @@
         }
     }
 
+    public void recreateDb() {
+        LauncherAppState app = LauncherAppState.getInstance();
+        app.recreateWidgetPreviewDb();
+        mDb = app.getWidgetPreviewCacheDb();
+    }
+
     public void setPreviewSize(int previewWidth, int previewHeight,
             PagedViewCellLayout widgetSpacingLayout) {
         mPreviewBitmapWidth = previewWidth;
@@ -177,18 +194,19 @@
         final String name = getObjectName(o);
         final String packageName = getObjectPackage(o);
         // check if the package is valid
-        boolean packageValid = true;
         synchronized(sInvalidPackages) {
-            packageValid = !sInvalidPackages.contains(packageName);
+            boolean packageValid = !sInvalidPackages.contains(packageName);
+            if (!packageValid) {
+                return null;
+            }
         }
-        if (!packageValid) {
-            return null;
-        }
-        if (packageValid) {
-            synchronized(mLoadedPreviews) {
-                // check if it exists in our existing cache
-                if (mLoadedPreviews.containsKey(name) && mLoadedPreviews.get(name).get() != null) {
-                    return mLoadedPreviews.get(name).get();
+        synchronized(mLoadedPreviews) {
+            // check if it exists in our existing cache
+            if (mLoadedPreviews.containsKey(name)) {
+                WeakReference<Bitmap> bitmapReference = mLoadedPreviews.get(name);
+                Bitmap bitmap = bitmapReference.get();
+                if (bitmap != null) {
+                    return bitmap;
                 }
             }
         }
@@ -196,11 +214,13 @@
         Bitmap unusedBitmap = null;
         synchronized(mUnusedBitmaps) {
             // not in cache; we need to load it from the db
-            while ((unusedBitmap == null || !unusedBitmap.isMutable() ||
-                    unusedBitmap.getWidth() != mPreviewBitmapWidth ||
-                    unusedBitmap.getHeight() != mPreviewBitmapHeight)
-                    && mUnusedBitmaps.size() > 0) {
-                unusedBitmap = mUnusedBitmaps.remove(0).get();
+            while (unusedBitmap == null && mUnusedBitmaps.size() > 0) {
+                Bitmap candidate = mUnusedBitmaps.remove(0).get();
+                if (candidate != null && candidate.isMutable() &&
+                        candidate.getWidth() == mPreviewBitmapWidth &&
+                        candidate.getHeight() == mPreviewBitmapHeight) {
+                    unusedBitmap = candidate;
+                }
             }
             if (unusedBitmap != null) {
                 final Canvas c = mCachedAppWidgetPreviewCanvas.get();
@@ -214,12 +234,7 @@
             unusedBitmap = Bitmap.createBitmap(mPreviewBitmapWidth, mPreviewBitmapHeight,
                     Bitmap.Config.ARGB_8888);
         }
-
-        Bitmap preview = null;
-
-        if (packageValid) {
-            preview = readFromDb(name, unusedBitmap);
-        }
+        Bitmap preview = readFromDb(name, unusedBitmap);
 
         if (preview != null) {
             synchronized(mLoadedPreviews) {
@@ -313,7 +328,7 @@
         String output;
         if (o instanceof AppWidgetProviderInfo) {
             sb.append(WIDGET_PREFIX);
-            sb.append(((AppWidgetProviderInfo) o).provider.flattenToString());
+            sb.append(((AppWidgetProviderInfo) o).toString());
             output = sb.toString();
             sb.setLength(0);
         } else {
@@ -347,13 +362,26 @@
         preview.compress(Bitmap.CompressFormat.PNG, 100, stream);
         values.put(CacheDb.COLUMN_PREVIEW_BITMAP, stream.toByteArray());
         values.put(CacheDb.COLUMN_SIZE, mSize);
-        db.insert(CacheDb.TABLE_NAME, null, values);
+        try {
+            db.insert(CacheDb.TABLE_NAME, null, values);
+        } catch (SQLiteDiskIOException e) {
+            recreateDb();
+        } catch (SQLiteCantOpenDatabaseException e) {
+            dumpOpenFiles();
+            throw e;
+        }
     }
 
     private void clearDb() {
         SQLiteDatabase db = mDb.getWritableDatabase();
         // Delete everything
-        db.delete(CacheDb.TABLE_NAME, null, null);
+        try {
+            db.delete(CacheDb.TABLE_NAME, null, null);
+        } catch (SQLiteDiskIOException e) {
+        } catch (SQLiteCantOpenDatabaseException e) {
+            dumpOpenFiles();
+            throw e;
+        }
     }
 
     public static void removePackageFromDb(final CacheDb cacheDb, final String packageName) {
@@ -363,13 +391,20 @@
         new AsyncTask<Void, Void, Void>() {
             public Void doInBackground(Void ... args) {
                 SQLiteDatabase db = cacheDb.getWritableDatabase();
-                db.delete(CacheDb.TABLE_NAME,
-                        CacheDb.COLUMN_NAME + " LIKE ? OR " +
-                        CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query
-                        new String[] {
-                            WIDGET_PREFIX + packageName + "/%",
-                            SHORTCUT_PREFIX + packageName + "/%"} // args to SELECT query
-                            );
+                try {
+                    db.delete(CacheDb.TABLE_NAME,
+                            CacheDb.COLUMN_NAME + " LIKE ? OR " +
+                            CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query
+                            new String[] {
+                                    WIDGET_PREFIX + packageName + "/%",
+                                    SHORTCUT_PREFIX + packageName + "/%"
+                            } // args to SELECT query
+                    );
+                } catch (SQLiteDiskIOException e) {
+                } catch (SQLiteCantOpenDatabaseException e) {
+                    dumpOpenFiles();
+                    throw e;
+                }
                 synchronized(sInvalidPackages) {
                     sInvalidPackages.remove(packageName);
                 }
@@ -378,13 +413,19 @@
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
     }
 
-    public static void removeItemFromDb(final CacheDb cacheDb, final String objectName) {
+    private static void removeItemFromDb(final CacheDb cacheDb, final String objectName) {
         new AsyncTask<Void, Void, Void>() {
             public Void doInBackground(Void ... args) {
                 SQLiteDatabase db = cacheDb.getWritableDatabase();
-                db.delete(CacheDb.TABLE_NAME,
-                        CacheDb.COLUMN_NAME + " = ? ", // SELECT query
-                        new String[] { objectName }); // args to SELECT query
+                try {
+                    db.delete(CacheDb.TABLE_NAME,
+                            CacheDb.COLUMN_NAME + " = ? ", // SELECT query
+                            new String[] { objectName }); // args to SELECT query
+                } catch (SQLiteDiskIOException e) {
+                } catch (SQLiteCantOpenDatabaseException e) {
+                    dumpOpenFiles();
+                    throw e;
+                }
                 return null;
             }
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
@@ -396,14 +437,23 @@
                     CacheDb.COLUMN_SIZE + " = ?";
         }
         SQLiteDatabase db = mDb.getReadableDatabase();
-        Cursor result = db.query(CacheDb.TABLE_NAME,
-                new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return
-                mCachedSelectQuery, // select query
-                new String[] { name, mSize }, // args to select query
-                null,
-                null,
-                null,
-                null);
+        Cursor result;
+        try {
+            result = db.query(CacheDb.TABLE_NAME,
+                    new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return
+                    mCachedSelectQuery, // select query
+                    new String[] { name, mSize }, // args to select query
+                    null,
+                    null,
+                    null,
+                    null);
+        } catch (SQLiteDiskIOException e) {
+            recreateDb();
+            return null;
+        } catch (SQLiteCantOpenDatabaseException e) {
+            dumpOpenFiles();
+            throw e;
+        }
         if (result.getCount() > 0) {
             result.moveToFirst();
             byte[] blob = result.getBlob(0);
@@ -423,7 +473,7 @@
         }
     }
 
-    public Bitmap generatePreview(Object info, Bitmap preview) {
+    private Bitmap generatePreview(Object info, Bitmap preview) {
         if (preview != null &&
                 (preview.getWidth() != mPreviewBitmapWidth ||
                 preview.getHeight() != mPreviewBitmapHeight)) {
@@ -441,8 +491,8 @@
         int[] cellSpans = Launcher.getSpanForWidget(mContext, info);
         int maxWidth = maxWidthForWidgetPreview(cellSpans[0]);
         int maxHeight = maxHeightForWidgetPreview(cellSpans[1]);
-        return generateWidgetPreview(info.provider, info.previewImage, info.icon,
-                cellSpans[0], cellSpans[1], maxWidth, maxHeight, preview, null);
+        return generateWidgetPreview(info, cellSpans[0], cellSpans[1],
+                maxWidth, maxHeight, preview, null);
     }
 
     public int maxWidthForWidgetPreview(int spanX) {
@@ -455,20 +505,20 @@
                 mWidgetSpacingLayout.estimateCellHeight(spanY));
     }
 
-    public Bitmap generateWidgetPreview(ComponentName provider, int previewImage,
-            int iconId, int cellHSpan, int cellVSpan, int maxPreviewWidth, int maxPreviewHeight,
-            Bitmap preview, int[] preScaledWidthOut) {
+    public Bitmap generateWidgetPreview(AppWidgetProviderInfo info, int cellHSpan, int cellVSpan,
+            int maxPreviewWidth, int maxPreviewHeight, Bitmap preview, int[] preScaledWidthOut) {
         // Load the preview image if possible
-        String packageName = provider.getPackageName();
         if (maxPreviewWidth < 0) maxPreviewWidth = Integer.MAX_VALUE;
         if (maxPreviewHeight < 0) maxPreviewHeight = Integer.MAX_VALUE;
 
         Drawable drawable = null;
-        if (previewImage != 0) {
-            drawable = mPackageManager.getDrawable(packageName, previewImage, null);
-            if (drawable == null) {
+        if (info.previewImage != 0) {
+            drawable = mManager.loadPreview(info);
+            if (drawable != null) {
+                drawable = mutateOnMainThread(drawable);
+            } else {
                 Log.w(TAG, "Can't load widget preview drawable 0x" +
-                        Integer.toHexString(previewImage) + " for provider: " + provider);
+                        Integer.toHexString(info.previewImage) + " for provider: " + info.provider);
             }
         }
 
@@ -484,6 +534,7 @@
             if (cellHSpan < 1) cellHSpan = 1;
             if (cellVSpan < 1) cellVSpan = 1;
 
+            // This Drawable is not directly drawn, so there's no need to mutate it.
             BitmapDrawable previewDrawable = (BitmapDrawable) mContext.getResources()
                     .getDrawable(R.drawable.widget_tile);
             final int previewDrawableWidth = previewDrawable
@@ -493,31 +544,33 @@
             previewWidth = previewDrawableWidth * cellHSpan;
             previewHeight = previewDrawableHeight * cellVSpan;
 
-            defaultPreview = Bitmap.createBitmap(previewWidth, previewHeight,
-                    Config.ARGB_8888);
+            defaultPreview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
             final Canvas c = mCachedAppWidgetPreviewCanvas.get();
             c.setBitmap(defaultPreview);
-            previewDrawable.setBounds(0, 0, previewWidth, previewHeight);
-            previewDrawable.setTileModeXY(Shader.TileMode.REPEAT,
-                    Shader.TileMode.REPEAT);
-            previewDrawable.draw(c);
+            Paint p = mDefaultAppWidgetPreviewPaint.get();
+            if (p == null) {
+                p = new Paint();
+                p.setShader(new BitmapShader(previewDrawable.getBitmap(),
+                        Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
+                mDefaultAppWidgetPreviewPaint.set(p);
+            }
+            final Rect dest = mCachedAppWidgetPreviewDestRect.get();
+            dest.set(0, 0, previewWidth, previewHeight);
+            c.drawRect(dest, p);
             c.setBitmap(null);
 
             // Draw the icon in the top left corner
-            int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
+            int minOffset = (int) (mAppIconSize * WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE);
             int smallestSide = Math.min(previewWidth, previewHeight);
             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);
+                Drawable icon = mManager.loadIcon(info, mIconCache);
                 if (icon != null) {
+                    int hoffset = (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
+                    int yoffset = (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
+                    icon = mutateOnMainThread(icon);
                     renderDrawableToBitmap(icon, defaultPreview, hoffset,
                             yoffset, (int) (mAppIconSize * iconScale),
                             (int) (mAppIconSize * iconScale));
@@ -567,7 +620,7 @@
             c.drawBitmap(defaultPreview, src, dest, p);
             c.setBitmap(null);
         }
-        return preview;
+        return mManager.getBadgeBitmap(info, preview);
     }
 
     private Bitmap generateShortcutPreview(
@@ -585,7 +638,7 @@
             c.setBitmap(null);
         }
         // Render the icon
-        Drawable icon = mIconCache.getFullResIcon(info);
+        Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info));
 
         int paddingTop = mContext.
                 getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
@@ -625,18 +678,10 @@
         return preview;
     }
 
-
-    public static void renderDrawableToBitmap(
-            Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
-        renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
-    }
-
     private static void renderDrawableToBitmap(
-            Drawable d, Bitmap bitmap, int x, int y, int w, int h,
-            float scale) {
+            Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
         if (bitmap != null) {
             Canvas c = new Canvas(bitmap);
-            c.scale(scale, scale);
             Rect oldBounds = d.copyBounds();
             d.setBounds(x, y, x + w, y + h);
             d.draw(c);
@@ -645,4 +690,98 @@
         }
     }
 
+    private Drawable mutateOnMainThread(final Drawable drawable) {
+        try {
+            return mMainThreadExecutor.submit(new Callable<Drawable>() {
+                @Override
+                public Drawable call() throws Exception {
+                    return drawable.mutate();
+                }
+            }).get();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException(e);
+        } catch (ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static final int MAX_OPEN_FILES = 1024;
+    private static final int SAMPLE_RATE = 23;
+    /**
+     * Dumps all files that are open in this process without allocating a file descriptor.
+     */
+    private static void dumpOpenFiles() {
+        try {
+            Log.i(TAG, "DUMP OF OPEN FILES (sample rate: 1 every " + SAMPLE_RATE + "):");
+            final String TYPE_APK = "apk";
+            final String TYPE_JAR = "jar";
+            final String TYPE_PIPE = "pipe";
+            final String TYPE_SOCKET = "socket";
+            final String TYPE_DB = "db";
+            final String TYPE_ANON_INODE = "anon_inode";
+            final String TYPE_DEV = "dev";
+            final String TYPE_NON_FS = "non-fs";
+            final String TYPE_OTHER = "other";
+            List<String> types = Arrays.asList(TYPE_APK, TYPE_JAR, TYPE_PIPE, TYPE_SOCKET, TYPE_DB,
+                    TYPE_ANON_INODE, TYPE_DEV, TYPE_NON_FS, TYPE_OTHER);
+            int[] count = new int[types.size()];
+            int[] duplicates = new int[types.size()];
+            HashSet<String> files = new HashSet<String>();
+            int total = 0;
+            for (int i = 0; i < MAX_OPEN_FILES; i++) {
+                // This is a gigantic hack but unfortunately the only way to resolve an fd
+                // to a file name. Note that we have to loop over all possible fds because
+                // reading the directory would require allocating a new fd. The kernel is
+                // currently implemented such that no fd is larger then the current rlimit,
+                // which is why it's safe to loop over them in such a way.
+                String fd = "/proc/self/fd/" + i;
+                try {
+                    // getCanonicalPath() uses readlink behind the scene which doesn't require
+                    // a file descriptor.
+                    String resolved = new File(fd).getCanonicalPath();
+                    int type = types.indexOf(TYPE_OTHER);
+                    if (resolved.startsWith("/dev/")) {
+                        type = types.indexOf(TYPE_DEV);
+                    } else if (resolved.endsWith(".apk")) {
+                        type = types.indexOf(TYPE_APK);
+                    } else if (resolved.endsWith(".jar")) {
+                        type = types.indexOf(TYPE_JAR);
+                    } else if (resolved.contains("/fd/pipe:")) {
+                        type = types.indexOf(TYPE_PIPE);
+                    } else if (resolved.contains("/fd/socket:")) {
+                        type = types.indexOf(TYPE_SOCKET);
+                    } else if (resolved.contains("/fd/anon_inode:")) {
+                        type = types.indexOf(TYPE_ANON_INODE);
+                    } else if (resolved.endsWith(".db") || resolved.contains("/databases/")) {
+                        type = types.indexOf(TYPE_DB);
+                    } else if (resolved.startsWith("/proc/") && resolved.contains("/fd/")) {
+                        // Those are the files that don't point anywhere on the file system.
+                        // getCanonicalPath() wrongly interprets these as relative symlinks and
+                        // resolves them within /proc/<pid>/fd/.
+                        type = types.indexOf(TYPE_NON_FS);
+                    }
+                    count[type]++;
+                    total++;
+                    if (files.contains(resolved)) {
+                        duplicates[type]++;
+                    }
+                    files.add(resolved);
+                    if (total % SAMPLE_RATE == 0) {
+                        Log.i(TAG, " fd " + i + ": " + resolved
+                                + " (" + types.get(type) + ")");
+                    }
+                } catch (IOException e) {
+                    // Ignoring exceptions for non-existing file descriptors.
+                }
+            }
+            for (int i = 0; i < types.size(); i++) {
+                Log.i(TAG, String.format("Open %10s files: %4d total, %4d duplicates",
+                        types.get(i), count[i], duplicates[i]));
+            }
+        } catch (Throwable t) {
+            // Catch everything. This is called from an exception handler that we shouldn't upset.
+            Log.e(TAG, "Unable to log open files.", t);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2ce9eb3..774996e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -31,12 +31,16 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -44,6 +48,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.support.v4.view.ViewCompat;
@@ -63,11 +68,17 @@
 import com.android.launcher3.FolderIcon.FolderRingAnimator;
 import com.android.launcher3.Launcher.CustomContentCallbacks;
 import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+import com.android.launcher3.compat.UserHandleCompat;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -96,6 +107,9 @@
 
     private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
 
+    static final boolean MAP_NO_RECURSE = false;
+    static final boolean MAP_RECURSE = true;
+
     // These animators are used to fade the children's outlines
     private ObjectAnimator mChildrenOutlineFadeInAnimation;
     private ObjectAnimator mChildrenOutlineFadeOutAnimation;
@@ -104,9 +118,6 @@
     // These properties refer to the background protection gradient used for AllApps and Customize
     private ValueAnimator mBackgroundFadeInAnimation;
     private ValueAnimator mBackgroundFadeOutAnimation;
-    private Drawable mBackground;
-    boolean mDrawBackground = true;
-    private float mBackgroundAlpha = 0;
 
     private static final long CUSTOM_CONTENT_GESTURE_DELAY = 200;
     private long mTouchDownTime = -1;
@@ -123,13 +134,14 @@
     private static boolean sAccessibilityEnabled;
 
     // The screen id used for the empty screen always present to the right.
-    private final static long EXTRA_EMPTY_SCREEN_ID = -201;
+    final static long EXTRA_EMPTY_SCREEN_ID = -201;
     private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
 
     private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>();
     private ArrayList<Long> mScreenOrder = new ArrayList<Long>();
 
     private Runnable mRemoveEmptyScreenRunnable;
+    private boolean mDeferRemoveExtraEmptyScreen = false;
 
     /**
      * CellInfo for the cell that is currently being dragged
@@ -185,7 +197,7 @@
     // State variable that indicates whether the pages are small (ie when you're
     // in all apps or customize mode)
 
-    enum State { NORMAL, SPRING_LOADED, SMALL, OVERVIEW};
+    enum State { NORMAL, NORMAL_HIDDEN, SPRING_LOADED, OVERVIEW, OVERVIEW_HIDDEN};
     private State mState = State.NORMAL;
     private boolean mIsSwitchingState = false;
 
@@ -200,15 +212,18 @@
 
     private HolographicOutlineHelper mOutlineHelper;
     private Bitmap mDragOutline = null;
-    private final Rect mTempRect = new Rect();
+    private static final Rect sTempRect = new Rect();
     private final int[] mTempXY = new int[2];
     private int[] mTempVisiblePagesRange = new int[2];
-    private boolean mOverscrollTransformsSet;
-    private float mLastOverscrollPivotX;
+    private boolean mOverscrollEffectSet;
     public static final int DRAG_BITMAP_PADDING = 2;
     private boolean mWorkspaceFadeInAdjacentScreens;
 
     WallpaperOffsetInterpolator mWallpaperOffset;
+    private boolean mWallpaperIsLiveWallpaper;
+    private int mNumPagesForWallpaperParallax;
+    private float mLastSetWallpaperOffsetSteps = 0;
+
     private Runnable mDelayedResizeRunnable;
     private Runnable mDelayedSnapToPageRunnable;
     private Point mDisplaySize = new Point();
@@ -226,6 +241,8 @@
     private DropTarget.DragEnforcer mDragEnforcer;
     private float mMaxDistanceForFolderCreation;
 
+    private final Canvas mCanvas = new Canvas();
+
     // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
     private float mXDown;
     private float mYDown;
@@ -266,6 +283,8 @@
     private int mLastChildCount = -1;
     private float mTransitionProgress;
 
+    float mOverScrollEffect = 0f;
+
     private Runnable mDeferredAction;
     private boolean mDeferDropAfterUninstall;
     private boolean mUninstallSuccessful;
@@ -388,13 +407,23 @@
             @Override
             public void run() {
                 if (mIsDragOccuring) {
+                    mDeferRemoveExtraEmptyScreen = false;
                     addExtraEmptyScreenOnDrag();
                 }
             }
         });
     }
 
+
+    public void deferRemoveExtraEmptyScreen() {
+        mDeferRemoveExtraEmptyScreen = true;
+    }
+
     public void onDragEnd() {
+        if (!mDeferRemoveExtraEmptyScreen) {
+            removeExtraEmptyScreen(true, mDragSourceInternal != null);
+        }
+
         mIsDragOccuring = false;
         updateChildrenLayersEnabled(false);
         mLauncher.unlockScreenOrientation(false);
@@ -411,7 +440,6 @@
      * Initializes various states for this workspace.
      */
     protected void initWorkspace() {
-        Context context = getContext();
         mCurrentPage = mDefaultPage;
         Launcher.setScreen(mCurrentPage);
         LauncherAppState app = LauncherAppState.getInstance();
@@ -421,17 +449,10 @@
         setClipChildren(false);
         setClipToPadding(false);
         setChildrenDrawnWithCacheEnabled(true);
-        
+
         setMinScale(mOverviewModeShrinkFactor);
         setupLayoutTransition();
 
-        final Resources res = getResources();
-        try {
-            mBackground = res.getDrawable(R.drawable.apps_customize_bg);
-        } catch (Resources.NotFoundException e) {
-            // In this case, we will skip drawing background protection
-        }
-
         mWallpaperOffset = new WallpaperOffsetInterpolator();
         Display display = mLauncher.getWindowManager().getDefaultDisplay();
         display.getSize(mDisplaySize);
@@ -562,10 +583,11 @@
         return screenId;
     }
 
-    public void createCustomContentPage() {
+    public void createCustomContentContainer() {
         CellLayout customScreen = (CellLayout)
                 mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
         customScreen.disableBackground();
+        customScreen.disableDragTarget();
 
         mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen);
         mScreenOrder.add(0, CUSTOM_CONTENT_SCREEN_ID);
@@ -579,7 +601,6 @@
         mDefaultPage = mOriginalDefaultPage + 1;
 
         // Update the custom content hint
-        mLauncher.getLauncherClings().updateCustomContentHintVisibility();
         if (mRestorePage != INVALID_RESTORE_PAGE) {
             mRestorePage = mRestorePage + 1;
         } else {
@@ -608,7 +629,6 @@
         mDefaultPage = mOriginalDefaultPage - 1;
 
         // Update the custom content hint
-        mLauncher.getLauncherClings().updateCustomContentHintVisibility();
         if (mRestorePage != INVALID_RESTORE_PAGE) {
             mRestorePage = mRestorePage - 1;
         } else {
@@ -689,6 +709,12 @@
         // Log to disk
         Launcher.addDumpLog(TAG, "11683562 - convertFinalScreenToEmptyScreenIfNecessary()", true);
 
+        if (mLauncher.isWorkspaceLoading()) {
+            // Invalid and dangerous operation if workspace is loading
+            Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
+            return;
+        }
+
         if (hasExtraEmptyScreen() || mScreenOrder.size() == 0) return;
         long finalScreenId = mScreenOrder.get(mScreenOrder.size() - 1);
 
@@ -711,21 +737,26 @@
         }
     }
 
-    public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete) {
-        removeExtraEmptyScreen(animate, onComplete, 0, false);
+    public void removeExtraEmptyScreen(final boolean animate, boolean stripEmptyScreens) {
+        removeExtraEmptyScreenDelayed(animate, null, 0, stripEmptyScreens);
     }
 
-    public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete,
+    public void removeExtraEmptyScreenDelayed(final boolean animate, final Runnable onComplete,
             final int delay, final boolean stripEmptyScreens) {
         // Log to disk
         Launcher.addDumpLog(TAG, "11683562 - removeExtraEmptyScreen()", true);
+        if (mLauncher.isWorkspaceLoading()) {
+            // Don't strip empty screens if the workspace is still loading
+            Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
+            return;
+        }
+
         if (delay > 0) {
             postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    removeExtraEmptyScreen(animate, onComplete, 0, stripEmptyScreens);
+                    removeExtraEmptyScreenDelayed(animate, onComplete, 0, stripEmptyScreens);
                 }
-
             }, delay);
             return;
         }
@@ -803,6 +834,11 @@
     public long commitExtraEmptyScreen() {
         // Log to disk
         Launcher.addDumpLog(TAG, "11683562 - commitExtraEmptyScreen()", true);
+        if (mLauncher.isWorkspaceLoading()) {
+            // Invalid and dangerous operation if workspace is loading
+            Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
+            return -1;
+        }
 
         int index = getPageIndexForScreenId(EXTRA_EMPTY_SCREEN_ID);
         CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
@@ -859,6 +895,13 @@
         // Log to disk
         Launcher.addDumpLog(TAG, "11683562 - stripEmptyScreens()", true);
 
+        if (mLauncher.isWorkspaceLoading()) {
+            // Don't strip empty screens if the workspace is still loading.
+            // This is dangerous and can result in data loss.
+            Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
+            return;
+        }
+
         if (isPageMoving()) {
             mStripScreensOnPageStopMoving = true;
             return;
@@ -959,7 +1002,7 @@
         final CellLayout layout;
         if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
             layout = mLauncher.getHotseat().getLayout();
-            child.setOnKeyListener(null);
+            child.setOnKeyListener(new HotseatIconKeyEventListener());
 
             // Hide folder title in the hotseat
             if (child instanceof FolderIcon) {
@@ -1025,8 +1068,8 @@
      */
     @Override
     public boolean onTouch(View v, MotionEvent event) {
-        return (isSmall() || !isFinishedSwitchingState())
-                || (!isSmall() && indexOfChild(v) != mCurrentPage);
+        return (workspaceInModalState() || !isFinishedSwitchingState())
+                || (!workspaceInModalState() && indexOfChild(v) != mCurrentPage);
     }
 
     public boolean isSwitchingState() {
@@ -1045,7 +1088,7 @@
 
     @Override
     public boolean dispatchUnhandledMove(View focused, int direction) {
-        if (isSmall() || !isFinishedSwitchingState()) {
+        if (workspaceInModalState() || !isFinishedSwitchingState()) {
             // when the home screens are shrunken, shouldn't allow side-scrolling
             return false;
         }
@@ -1064,7 +1107,7 @@
         case MotionEvent.ACTION_UP:
             if (mTouchState == TOUCH_STATE_REST) {
                 final CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
-                if (!currentPage.lastDownOnOccupiedCell()) {
+                if (currentPage != null && !currentPage.lastDownOnOccupiedCell()) {
                     onWallpaperTap(ev);
                 }
             }
@@ -1072,6 +1115,17 @@
         return super.onInterceptTouchEvent(ev);
     }
 
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        // Ignore pointer scroll events if the custom content doesn't allow scrolling.
+        if ((getScreenIdForPageIndex(getCurrentPage()) == CUSTOM_CONTENT_SCREEN_ID)
+                && (mCustomContentCallbacks != null)
+                && !mCustomContentCallbacks.isScrollingAllowed()) {
+            return false;
+        }
+        return super.onGenericMotionEvent(event);
+    }
+
     protected void reinflateWidgetsIfNecessary() {
         final int clCount = getChildCount();
         for (int i = 0; i < clCount; i++) {
@@ -1081,10 +1135,10 @@
             for (int j = 0; j < itemCount; j++) {
                 View v = swc.getChildAt(j);
 
-                if (v.getTag() instanceof LauncherAppWidgetInfo) {
+                if (v != null  && v.getTag() instanceof LauncherAppWidgetInfo) {
                     LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
                     LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
-                    if (lahv != null && lahv.orientationChangedSincedInflation()) {
+                    if (lahv != null && lahv.isReinflateRequired()) {
                         mLauncher.removeAppWidget(info);
                         // Remove the current widget which is inflated with the wrong orientation
                         cl.removeView(lahv);
@@ -1116,12 +1170,20 @@
                 (mTouchDownTime - mCustomContentShowTime) > CUSTOM_CONTENT_GESTURE_DELAY;
 
         boolean swipeInIgnoreDirection = isLayoutRtl() ? deltaX < 0 : deltaX > 0;
-        if (swipeInIgnoreDirection && getScreenIdForPageIndex(getCurrentPage()) ==
-                CUSTOM_CONTENT_SCREEN_ID && passRightSwipesToCustomContent) {
+        boolean onCustomContentScreen =
+                getScreenIdForPageIndex(getCurrentPage()) == CUSTOM_CONTENT_SCREEN_ID;
+        if (swipeInIgnoreDirection && onCustomContentScreen && passRightSwipesToCustomContent) {
             // Pass swipes to the right to the custom content page.
             return;
         }
 
+        if (onCustomContentScreen && (mCustomContentCallbacks != null)
+                && !mCustomContentCallbacks.isScrollingAllowed()) {
+            // Don't allow workspace scrolling if the current custom content screen doesn't allow
+            // scrolling.
+            return;
+        }
+
         if (theta > MAX_SWIPE_ANGLE) {
             // Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
             return;
@@ -1155,14 +1217,6 @@
                 enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
             }
         }
-
-        // If we are not fading in adjacent screens, we still need to restore the alpha in case the
-        // user scrolls while we are transitioning (should not affect dispatchDraw optimizations)
-        if (!mWorkspaceFadeInAdjacentScreens) {
-            for (int i = 0; i < getChildCount(); ++i) {
-                ((CellLayout) getPageAt(i)).setShortcutAndWidgetAlpha(1f);
-            }
-        }
     }
 
     protected void onPageEndMoving() {
@@ -1175,7 +1229,7 @@
         }
 
         if (mDragController.isDragging()) {
-            if (isSmall()) {
+            if (workspaceInModalState()) {
                 // If we are in springloaded mode, then force an event to check if the current touch
                 // is under a new page (to scroll to)
                 mDragController.forceTouchMove();
@@ -1205,7 +1259,7 @@
         if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) {
             mCustomContentShowing = true;
             if (mCustomContentCallbacks != null) {
-                mCustomContentCallbacks.onShow();
+                mCustomContentCallbacks.onShow(false);
                 mCustomContentShowTime = System.currentTimeMillis();
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }
@@ -1217,9 +1271,6 @@
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }
         }
-        if (getPageIndicator() != null) {
-            getPageIndicator().setContentDescription(getPageIndicatorDescription());
-        }
     }
 
     protected CustomContentCallbacks getCustomContentCallbacks() {
@@ -1233,7 +1284,8 @@
                 SharedPreferences sp =
                         mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
                 LauncherWallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
-                        sp, mLauncher.getWindowManager(), mWallpaperManager);
+                        sp, mLauncher.getWindowManager(), mWallpaperManager,
+                        mLauncher.overrideWallpaperDimensions());
                 return null;
             }
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
@@ -1251,6 +1303,10 @@
         snapToPage(whichPage, duration);
     }
 
+    public void snapToScreenId(long screenId) {
+        snapToScreenId(screenId, null);
+    }
+
     protected void snapToScreenId(long screenId, Runnable r) {
         snapToPage(getPageIndexForScreenId(screenId), r);
     }
@@ -1347,7 +1403,14 @@
                 // Don't use up all the wallpaper parallax until you have at least
                 // MIN_PARALLAX_PAGE_SPAN pages
                 int numScrollingPages = getNumScreensExcludingEmptyAndCustom();
-                int parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+                int parallaxPageSpan;
+                if (mWallpaperIsLiveWallpaper) {
+                    parallaxPageSpan = numScrollingPages - 1;
+                } else {
+                    parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+                }
+                mNumPagesForWallpaperParallax = parallaxPageSpan;
+
                 // On RTL devices, push the wallpaper offset to the right if we don't have enough
                 // pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN)
                 int padding = isLayoutRtl() ? parallaxPageSpan - numScrollingPages + 1 : 0;
@@ -1391,7 +1454,11 @@
 
         private void setWallpaperOffsetSteps() {
             // Set wallpaper offset steps (1 / (number of screens - 1))
-            mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f);
+            float xOffset = 1.0f / mNumPagesForWallpaperParallax;
+            if (xOffset != mLastSetWallpaperOffsetSteps) {
+                mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f);
+                mLastSetWallpaperOffsetSteps = xOffset;
+            }
         }
 
         public void setFinalX(float x) {
@@ -1424,8 +1491,16 @@
         mWallpaperOffset.syncWithScroll();
     }
 
+    @Override
+    public void announceForAccessibility(CharSequence text) {
+        // Don't announce if apps is on top of us.
+        if (!mLauncher.isAllAppsVisible()) {
+            super.announceForAccessibility(text);
+        }
+    }
+
     void showOutlines() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
             mChildrenOutlineFadeInAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 1.0f);
@@ -1435,7 +1510,7 @@
     }
 
     void hideOutlines() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
             mChildrenOutlineFadeOutAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 0.0f);
@@ -1463,15 +1538,9 @@
         return mChildrenOutlineAlpha;
     }
 
-    void disableBackground() {
-        mDrawBackground = false;
-    }
-    void enableBackground() {
-        mDrawBackground = true;
-    }
-
     private void animateBackgroundGradient(float finalAlpha, boolean animated) {
-        if (mBackground == null) return;
+        final DragLayer dragLayer = mLauncher.getDragLayer();
+
         if (mBackgroundFadeInAnimation != null) {
             mBackgroundFadeInAnimation.cancel();
             mBackgroundFadeInAnimation = null;
@@ -1480,36 +1549,26 @@
             mBackgroundFadeOutAnimation.cancel();
             mBackgroundFadeOutAnimation = null;
         }
-        float startAlpha = getBackgroundAlpha();
+        float startAlpha = dragLayer.getBackgroundAlpha();
         if (finalAlpha != startAlpha) {
             if (animated) {
                 mBackgroundFadeOutAnimation =
                         LauncherAnimUtils.ofFloat(this, startAlpha, finalAlpha);
                 mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
                     public void onAnimationUpdate(ValueAnimator animation) {
-                        setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
+                        dragLayer.setBackgroundAlpha(
+                                ((Float)animation.getAnimatedValue()).floatValue());
                     }
                 });
                 mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
                 mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
                 mBackgroundFadeOutAnimation.start();
             } else {
-                setBackgroundAlpha(finalAlpha);
+                dragLayer.setBackgroundAlpha(finalAlpha);
             }
         }
     }
 
-    public void setBackgroundAlpha(float alpha) {
-        if (alpha != mBackgroundAlpha) {
-            mBackgroundAlpha = alpha;
-            invalidate();
-        }
-    }
-
-    public float getBackgroundAlpha() {
-        return mBackgroundAlpha;
-    }
-
     float backgroundAlphaInterpolator(float r) {
         float pivotA = 0.1f;
         float pivotB = 0.4f;
@@ -1525,7 +1584,7 @@
     private void updatePageAlphaValues(int screenCenter) {
         boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
         if (mWorkspaceFadeInAdjacentScreens &&
-                mState == State.NORMAL &&
+                !workspaceInModalState() &&
                 !mIsSwitchingState &&
                 !isInOverscroll) {
             for (int i = numCustomPages(); i < getChildCount(); i++) {
@@ -1534,6 +1593,7 @@
                     float scrollProgress = getScrollProgress(screenCenter, child, i);
                     float alpha = 1 - Math.abs(scrollProgress);
                     child.getShortcutsAndWidgets().setAlpha(alpha);
+                    //child.setBackgroundAlphaMultiplier(1 - alpha);
                 }
             }
         }
@@ -1581,13 +1641,13 @@
         if (Float.compare(progress, mLastCustomContentScrollProgress) == 0) return;
 
         CellLayout cc = mWorkspaceScreens.get(CUSTOM_CONTENT_SCREEN_ID);
-        if (progress > 0 && cc.getVisibility() != VISIBLE && !isSmall()) {
+        if (progress > 0 && cc.getVisibility() != VISIBLE && !workspaceInModalState()) {
             cc.setVisibility(VISIBLE);
         }
 
         mLastCustomContentScrollProgress = progress;
 
-        setBackgroundAlpha(progress * 0.8f);
+        mLauncher.getDragLayer().setBackgroundAlpha(progress * 0.8f);
 
         if (mLauncher.getHotseat() != null) {
             mLauncher.getHotseat().setTranslationX(translationX);
@@ -1627,47 +1687,40 @@
         updateStateForCustomContent(screenCenter);
         enableHwLayersOnVisiblePages();
 
-        boolean shouldOverScroll = (mOverScrollX < 0 && (!hasCustomContent() || isLayoutRtl())) ||
-                (mOverScrollX > mMaxScrollX && (!hasCustomContent() || !isLayoutRtl()));
+        boolean shouldOverScroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
 
         if (shouldOverScroll) {
             int index = 0;
-            float pivotX = 0f;
-            final float leftBiasedPivot = 0.25f;
-            final float rightBiasedPivot = 0.75f;
             final int lowerIndex = 0;
             final int upperIndex = getChildCount() - 1;
 
             final boolean isLeftPage = mOverScrollX < 0;
             index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex;
-            pivotX = isLeftPage ? rightBiasedPivot : leftBiasedPivot;
 
             CellLayout cl = (CellLayout) getChildAt(index);
-            float scrollProgress = getScrollProgress(screenCenter, cl, index);
-            cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage);
-            float rotation = -WORKSPACE_OVERSCROLL_ROTATION * scrollProgress;
-            cl.setRotationY(rotation);
+            float effect = Math.abs(mOverScrollEffect);
+            cl.setOverScrollAmount(Math.abs(effect), isLeftPage);
 
-            if (!mOverscrollTransformsSet || Float.compare(mLastOverscrollPivotX, pivotX) != 0) {
-                mOverscrollTransformsSet = true;
-                mLastOverscrollPivotX = pivotX;
-                cl.setCameraDistance(mDensity * mCameraDistance);
-                cl.setPivotX(cl.getMeasuredWidth() * pivotX);
-                cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
-                cl.setOverscrollTransformsDirty(true);
-            }
+            mOverscrollEffectSet = true;
         } else {
-            if (mOverscrollTransformsSet && getChildCount() > 0) {
-                mOverscrollTransformsSet = false;
-                ((CellLayout) getChildAt(0)).resetOverscrollTransforms();
-                ((CellLayout) getChildAt(getChildCount() - 1)).resetOverscrollTransforms();
+            if (mOverscrollEffectSet && getChildCount() > 0) {
+                mOverscrollEffectSet = false;
+                ((CellLayout) getChildAt(0)).setOverScrollAmount(0, false);
+                ((CellLayout) getChildAt(getChildCount() - 1)).setOverScrollAmount(0, false);
             }
         }
     }
 
     @Override
     protected void overScroll(float amount) {
-        acceleratedOverScroll(amount);
+        boolean shouldOverScroll = (amount < 0 && (!hasCustomContent() || isLayoutRtl())) ||
+                (amount > 0 && (!hasCustomContent() || !isLayoutRtl()));
+        if (shouldOverScroll) {
+            dampedOverScroll(amount);
+            mOverScrollEffect = acceleratedOverFactor(amount);
+        } else {
+            mOverScrollEffect = 0;
+        }
     }
 
     protected void onAttachedToWindow() {
@@ -1700,6 +1753,10 @@
         if (LauncherAppState.getInstance().hasWallpaperChangedSinceLastCheck()) {
             setWallpaperDimension();
         }
+        mWallpaperIsLiveWallpaper = mWallpaperManager.getWallpaperInfo() != null;
+        // Force the wallpaper offset steps to be set again, because another app might have changed
+        // them
+        mLastSetWallpaperOffsetSteps = 0f;
     }
 
     @Override
@@ -1713,25 +1770,12 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        // Draw the background gradient if necessary
-        if (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground) {
-            int alpha = (int) (mBackgroundAlpha * 255);
-            mBackground.setAlpha(alpha);
-            mBackground.setBounds(getScrollX(), 0, getScrollX() + getMeasuredWidth(),
-                    getMeasuredHeight());
-            mBackground.draw(canvas);
-        }
-
         super.onDraw(canvas);
 
         // Call back to LauncherModel to finish binding after the first draw
         post(mBindPages);
     }
 
-    boolean isDrawingBackgroundGradient() {
-        return (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground);
-    }
-
     @Override
     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
         if (!mLauncher.isAllAppsVisible()) {
@@ -1747,7 +1791,7 @@
 
     @Override
     public int getDescendantFocusability() {
-        if (isSmall()) {
+        if (workspaceInModalState()) {
             return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
         }
         return super.getDescendantFocusability();
@@ -1765,8 +1809,8 @@
         }
     }
 
-    public boolean isSmall() {
-        return mState == State.SMALL || mState == State.SPRING_LOADED || mState == State.OVERVIEW;
+    public boolean workspaceInModalState() {
+        return mState != State.NORMAL;
     }
 
     void enableChildrenCache(int fromPage, int toPage) {
@@ -1801,7 +1845,7 @@
     }
 
     private void updateChildrenLayersEnabled(boolean force) {
-        boolean small = mState == State.SMALL || mState == State.OVERVIEW || mIsSwitchingState;
+        boolean small = mState == State.OVERVIEW || mIsSwitchingState;
         boolean enableChildrenLayers = force || small || mAnimatingViewIntoPlace || isPageMoving();
 
         if (enableChildrenLayers != mChildrenLayersEnabled) {
@@ -1939,21 +1983,54 @@
     * appearance).
     *
     */
-    public void onDragStartedWithItem(View v) {
-        final Canvas canvas = new Canvas();
+    private static Rect getDrawableBounds(Drawable d) {
+        Rect bounds = new Rect();
+        d.copyBounds(bounds);
+        if (bounds.width() == 0 || bounds.height() == 0) {
+            bounds.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+        } else {
+            bounds.offsetTo(0, 0);
+        }
+        if (d instanceof PreloadIconDrawable) {
+            int inset = -((PreloadIconDrawable) d).getOutset();
+            bounds.inset(inset, inset);
+        }
+        return bounds;
+    }
+
+    public void onExternalDragStartedWithItem(View v) {
+        // Compose a drag bitmap with the view scaled to the icon size
+        LauncherAppState app = LauncherAppState.getInstance();
+        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+        int iconSize = grid.iconSizePx;
+        int bmpWidth = v.getMeasuredWidth();
+        int bmpHeight = v.getMeasuredHeight();
+
+        // If this is a text view, use its drawable instead
+        if (v instanceof TextView) {
+            TextView tv = (TextView) v;
+            Drawable d = tv.getCompoundDrawables()[1];
+            Rect bounds = getDrawableBounds(d);
+            bmpWidth = bounds.width();
+            bmpHeight = bounds.height();
+        }
+
+        // Compose the bitmap to create the icon from
+        Bitmap b = Bitmap.createBitmap(bmpWidth, bmpHeight,
+                Bitmap.Config.ARGB_8888);
+        mCanvas.setBitmap(b);
+        drawDragView(v, mCanvas, 0);
+        mCanvas.setBitmap(null);
 
         // The outline is used to visualize where the item will land if dropped
-        mDragOutline = createDragOutline(v, canvas, DRAG_BITMAP_PADDING);
+        mDragOutline = createDragOutline(b, DRAG_BITMAP_PADDING, iconSize, iconSize, true);
     }
 
     public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, boolean clipAlpha) {
-        final Canvas canvas = new Canvas();
-
         int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
 
         // The outline is used to visualize where the item will land if dropped
-        mDragOutline = createDragOutline(b, canvas, DRAG_BITMAP_PADDING, size[0],
-                size[1], clipAlpha);
+        mDragOutline = createDragOutline(b, DRAG_BITMAP_PADDING, size[0], size[1], clipAlpha);
     }
 
     public void exitWidgetResizeMode() {
@@ -1971,18 +2048,23 @@
         mNewAlphas = new float[childCount];
     }
 
-    Animator getChangeStateAnimation(final State state, boolean animated) {
-        return getChangeStateAnimation(state, animated, 0, -1);
+    Animator getChangeStateAnimation(final State state, boolean animated,
+            ArrayList<View> layerViews) {
+        return getChangeStateAnimation(state, animated, 0, -1, layerViews);
     }
 
     @Override
-    protected void getOverviewModePages(int[] range) {
+    protected void getFreeScrollPageRange(int[] range) {
+        getOverviewModePages(range);
+    }
+
+    private void getOverviewModePages(int[] range) {
         int start = numCustomPages();
         int end = getChildCount() - 1;
 
         range[0] = Math.max(0, Math.min(start, getChildCount() - 1));
         range[1] = Math.max(0,  end);
-     }
+    }
 
     protected void onStartReordering() {
         super.onStartReordering();
@@ -1994,6 +2076,11 @@
     protected void onEndReordering() {
         super.onEndReordering();
 
+        if (mLauncher.isWorkspaceLoading()) {
+            // Invalid and dangerous operation if workspace is loading
+            return;
+        }
+
         hideOutlines();
         mScreenOrder.clear();
         int count = getChildCount();
@@ -2085,6 +2172,10 @@
         updateAccessibilityFlags();
     }
 
+    State getState() {
+        return mState;
+    }
+
     private void updateAccessibilityFlags() {
         int accessible = mState == State.NORMAL ?
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES :
@@ -2092,7 +2183,14 @@
         setImportantForAccessibility(accessible);
     }
 
+    private static final int HIDE_WORKSPACE_DURATION = 100;
+
     Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage) {
+        return getChangeStateAnimation(state, animated, delay, snapPage, null);
+    }
+
+    Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage,
+            ArrayList<View> layerViews) {
         if (mState == state) {
             return null;
         }
@@ -2105,21 +2203,25 @@
         final State oldState = mState;
         final boolean oldStateIsNormal = (oldState == State.NORMAL);
         final boolean oldStateIsSpringLoaded = (oldState == State.SPRING_LOADED);
-        final boolean oldStateIsSmall = (oldState == State.SMALL);
+        final boolean oldStateIsNormalHidden = (oldState == State.NORMAL_HIDDEN);
+        final boolean oldStateIsOverviewHidden = (oldState == State.OVERVIEW_HIDDEN);
         final boolean oldStateIsOverview = (oldState == State.OVERVIEW);
         setState(state);
         final boolean stateIsNormal = (state == State.NORMAL);
         final boolean stateIsSpringLoaded = (state == State.SPRING_LOADED);
-        final boolean stateIsSmall = (state == State.SMALL);
+        final boolean stateIsNormalHidden = (state == State.NORMAL_HIDDEN);
+        final boolean stateIsOverviewHidden = (state == State.OVERVIEW_HIDDEN);
         final boolean stateIsOverview = (state == State.OVERVIEW);
         float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f;
-        float finalHotseatAndPageIndicatorAlpha = (stateIsOverview || stateIsSmall) ? 0f : 1f;
+        float finalHotseatAndPageIndicatorAlpha = (stateIsNormal || stateIsSpringLoaded) ? 1f : 0f;
         float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
         float finalSearchBarAlpha = !stateIsNormal ? 0f : 1f;
-        float finalWorkspaceTranslationY = stateIsOverview ? getOverviewModeTranslationY() : 0;
+        float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ?
+                getOverviewModeTranslationY() : 0;
 
-        boolean workspaceToAllApps = (oldStateIsNormal && stateIsSmall);
-        boolean allAppsToWorkspace = (oldStateIsSmall && stateIsNormal);
+        boolean workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
+        boolean overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
+        boolean allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal);
         boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview);
         boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
 
@@ -2134,19 +2236,14 @@
         if (state != State.NORMAL) {
             if (stateIsSpringLoaded) {
                 mNewScale = mSpringLoadedShrinkFactor;
-            } else if (stateIsOverview) {
+            } else if (stateIsOverview || stateIsOverviewHidden) {
                 mNewScale = mOverviewModeShrinkFactor;
-            } else if (stateIsSmall){
-                mNewScale = mOverviewModeShrinkFactor - 0.3f;
-            }
-            if (workspaceToAllApps) {
-                updateChildrenLayersEnabled(false);
             }
         }
 
         final int duration;
-        if (workspaceToAllApps) {
-            duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
+        if (workspaceToAllApps || overviewToAllApps) {
+            duration = HIDE_WORKSPACE_DURATION; //getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
         } else if (workspaceToOverview || overviewToWorkspace) {
             duration = getResources().getInteger(R.integer.config_overviewTransitionTime);
         } else {
@@ -2163,7 +2260,7 @@
             boolean isCurrentPage = (i == snapPage);
             float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
             float finalAlpha;
-            if (stateIsSmall) {
+            if (stateIsNormalHidden || stateIsOverviewHidden) {
                 finalAlpha = 0f;
             } else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
                 finalAlpha = (i == snapPage || i < numCustomPages()) ? 1f : 0f;
@@ -2200,11 +2297,11 @@
         final View hotseat = mLauncher.getHotseat();
         final View pageIndicator = getPageIndicator();
         if (animated) {
-            anim.setDuration(duration);
             LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this);
             scale.scaleX(mNewScale)
                 .scaleY(mNewScale)
                 .translationY(finalWorkspaceTranslationY)
+                .setDuration(duration)
                 .setInterpolator(mZoomInInterpolator);
             anim.play(scale);
             for (int index = 0; index < getChildCount(); index++) {
@@ -2215,10 +2312,14 @@
                     cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
                     cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
                 } else {
+                    if (layerViews != null) {
+                        layerViews.add(cl);
+                    }
                     if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
                         LauncherViewPropertyAnimator alphaAnim =
                             new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
                         alphaAnim.alpha(mNewAlphas[i])
+                            .setDuration(duration)
                             .setInterpolator(mZoomInInterpolator);
                         anim.play(alphaAnim);
                     }
@@ -2227,6 +2328,7 @@
                         ValueAnimator bgAnim =
                                 LauncherAnimUtils.ofFloat(cl, 0f, 1f);
                         bgAnim.setInterpolator(mZoomInInterpolator);
+                        bgAnim.setDuration(duration);
                         bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
                                 public void onAnimationUpdate(float a, float b) {
                                     cl.setBackgroundAlpha(
@@ -2260,6 +2362,17 @@
                 .alpha(finalOverviewPanelAlpha).withLayer();
             overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
 
+            // For animation optimations, we may need to provide the Launcher transition
+            // with a set of views on which to force build layers in certain scenarios.
+            hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            if (layerViews != null) {
+                layerViews.add(hotseat);
+                layerViews.add(searchBar);
+                layerViews.add(overviewPanel);
+            }
+
             if (workspaceToOverview) {
                 pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
                 hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
@@ -2269,7 +2382,11 @@
                 hotseatAlpha.setInterpolator(null);
                 overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
             }
-            searchBarAlpha.setInterpolator(null);
+
+            overviewPanelAlpha.setDuration(duration);
+            pageIndicatorAlpha.setDuration(duration);
+            hotseatAlpha.setDuration(duration);
+            searchBarAlpha.setDuration(duration);
 
             anim.play(overviewPanelAlpha);
             anim.play(hotseatAlpha);
@@ -2294,18 +2411,11 @@
         }
         mLauncher.updateVoiceButtonProxyVisible(false);
 
-        if (stateIsSpringLoaded) {
-            // Right now we're covered by Apps Customize
-            // Show the background gradient immediately, so the gradient will
-            // be showing once AppsCustomize disappears
-            animateBackgroundGradient(getResources().getInteger(
-                    R.integer.config_appsCustomizeSpringLoadedBgAlpha) / 100f, false);
-        } else if (stateIsOverview) {
-            animateBackgroundGradient(getResources().getInteger(
-                    R.integer.config_appsCustomizeSpringLoadedBgAlpha) / 100f, true);
-        } else {
-            // Fade the background gradient away
+        if (stateIsNormal) {
             animateBackgroundGradient(0f, animated);
+        } else {
+            animateBackgroundGradient(getResources().getInteger(
+                    R.integer.config_workspaceScrimAlpha) / 100f, animated);
         }
         return anim;
     }
@@ -2408,21 +2518,6 @@
     private void onTransitionEnd() {
         mIsSwitchingState = false;
         updateChildrenLayersEnabled(false);
-        // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
-        // ensure that only the current page is visible during (and subsequently, after) the
-        // transition animation.  If fade adjacent pages is disabled, then re-enable the page
-        // visibility after the transition animation.
-        if (!mWorkspaceFadeInAdjacentScreens) {
-            for (int i = 0; i < getChildCount(); i++) {
-                final CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setShortcutAndWidgetAlpha(1f);
-            }
-        } else {
-            for (int i = 0; i < numCustomPages(); i++) {
-                final CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setShortcutAndWidgetAlpha(1f);
-            }
-        }
         showCustomContentIfNecessary();
     }
 
@@ -2438,17 +2533,18 @@
      * @param destCanvas the canvas to draw on
      * @param padding the horizontal and vertical padding to use when drawing
      */
-    private void drawDragView(View v, Canvas destCanvas, int padding, boolean pruneToDrawable) {
-        final Rect clipRect = mTempRect;
+    private static void drawDragView(View v, Canvas destCanvas, int padding) {
+        final Rect clipRect = sTempRect;
         v.getDrawingRect(clipRect);
 
         boolean textVisible = false;
 
         destCanvas.save();
-        if (v instanceof TextView && pruneToDrawable) {
+        if (v instanceof TextView) {
             Drawable d = ((TextView) v).getCompoundDrawables()[1];
-            clipRect.set(0, 0, d.getIntrinsicWidth() + padding, d.getIntrinsicHeight() + padding);
-            destCanvas.translate(padding / 2, padding / 2);
+            Rect bounds = getDrawableBounds(d);
+            clipRect.set(0, 0, bounds.width() + padding, bounds.height() + padding);
+            destCanvas.translate(padding / 2 - bounds.left, padding / 2 - bounds.top);
             d.draw(destCanvas);
         } else {
             if (v instanceof FolderIcon) {
@@ -2458,14 +2554,6 @@
                     ((FolderIcon) v).setTextVisible(false);
                     textVisible = true;
                 }
-            } else if (v instanceof BubbleTextView) {
-                final BubbleTextView tv = (BubbleTextView) v;
-                clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
-                        tv.getLayout().getLineTop(0);
-            } else if (v instanceof TextView) {
-                final TextView tv = (TextView) v;
-                clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() +
-                        tv.getLayout().getLineTop(0);
             }
             destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
             destCanvas.clipRect(clipRect, Op.REPLACE);
@@ -2482,22 +2570,27 @@
     /**
      * Returns a new bitmap to show when the given View is being dragged around.
      * Responsibility for the bitmap is transferred to the caller.
+     * @param expectedPadding padding to add to the drag view. If a different padding was used
+     * its value will be changed
      */
-    public Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
+    public Bitmap createDragBitmap(View v, AtomicInteger expectedPadding) {
         Bitmap b;
 
+        int padding = expectedPadding.get();
         if (v instanceof TextView) {
             Drawable d = ((TextView) v).getCompoundDrawables()[1];
-            b = Bitmap.createBitmap(d.getIntrinsicWidth() + padding,
-                    d.getIntrinsicHeight() + padding, Bitmap.Config.ARGB_8888);
+            Rect bounds = getDrawableBounds(d);
+            b = Bitmap.createBitmap(bounds.width() + padding,
+                    bounds.height() + padding, Bitmap.Config.ARGB_8888);
+            expectedPadding.set(padding - bounds.left - bounds.top);
         } else {
             b = Bitmap.createBitmap(
                     v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
         }
 
-        canvas.setBitmap(b);
-        drawDragView(v, canvas, padding, true);
-        canvas.setBitmap(null);
+        mCanvas.setBitmap(b);
+        drawDragView(v, mCanvas, padding);
+        mCanvas.setBitmap(null);
 
         return b;
     }
@@ -2506,15 +2599,15 @@
      * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
      * Responsibility for the bitmap is transferred to the caller.
      */
-    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
+    private Bitmap createDragOutline(View v, int padding) {
         final int outlineColor = getResources().getColor(R.color.outline_color);
         final Bitmap b = Bitmap.createBitmap(
                 v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
 
-        canvas.setBitmap(b);
-        drawDragView(v, canvas, padding, true);
-        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
-        canvas.setBitmap(null);
+        mCanvas.setBitmap(b);
+        drawDragView(v, mCanvas, padding);
+        mOutlineHelper.applyExpensiveOutlineWithBlur(b, mCanvas, outlineColor, outlineColor);
+        mCanvas.setBitmap(null);
         return b;
     }
 
@@ -2522,11 +2615,11 @@
      * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
      * Responsibility for the bitmap is transferred to the caller.
      */
-    private Bitmap createDragOutline(Bitmap orig, Canvas canvas, int padding, int w, int h,
+    private Bitmap createDragOutline(Bitmap orig, int padding, int w, int h,
             boolean clipAlpha) {
         final int outlineColor = getResources().getColor(R.color.outline_color);
         final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-        canvas.setBitmap(b);
+        mCanvas.setBitmap(b);
 
         Rect src = new Rect(0, 0, orig.getWidth(), orig.getHeight());
         float scaleFactor = Math.min((w - padding) / (float) orig.getWidth(),
@@ -2538,10 +2631,10 @@
         // center the image
         dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2);
 
-        canvas.drawBitmap(orig, src, dst, null);
-        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor,
+        mCanvas.drawBitmap(orig, src, dst, null);
+        mOutlineHelper.applyExpensiveOutlineWithBlur(b, mCanvas, outlineColor, outlineColor,
                 clipAlpha);
-        canvas.setBitmap(null);
+        mCanvas.setBitmap(null);
 
         return b;
     }
@@ -2559,35 +2652,34 @@
         CellLayout layout = (CellLayout) child.getParent().getParent();
         layout.prepareChildForDrag(child);
 
-        child.clearFocus();
-        child.setPressed(false);
-
-        final Canvas canvas = new Canvas();
-
-        // The outline is used to visualize where the item will land if dropped
-        mDragOutline = createDragOutline(child, canvas, DRAG_BITMAP_PADDING);
         beginDragShared(child, this);
     }
 
     public void beginDragShared(View child, DragSource source) {
+        child.clearFocus();
+        child.setPressed(false);
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(child, DRAG_BITMAP_PADDING);
+
+        mLauncher.onDragStarted(child);
         // The drag bitmap follows the touch point around on the screen
-        final Bitmap b = createDragBitmap(child, new Canvas(), DRAG_BITMAP_PADDING);
+        AtomicInteger padding = new AtomicInteger(DRAG_BITMAP_PADDING);
+        final Bitmap b = createDragBitmap(child, padding);
 
         final int bmpWidth = b.getWidth();
         final int bmpHeight = b.getHeight();
 
         float scale = mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
-        int dragLayerX =
-                Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);
-        int dragLayerY =
-                Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
-                        - DRAG_BITMAP_PADDING / 2);
+        int dragLayerX = Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);
+        int dragLayerY = Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
+                        - padding.get() / 2);
 
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
         Point dragVisualizeOffset = null;
         Rect dragRect = null;
-        if (child instanceof BubbleTextView || child instanceof PagedViewIcon) {
+        if (child instanceof BubbleTextView) {
             int iconSize = grid.iconSizePx;
             int top = child.getPaddingTop();
             int left = (bmpWidth - iconSize) / 2;
@@ -2596,7 +2688,7 @@
             dragLayerY += top;
             // Note: The drag region is used to calculate drag layer offsets, but the
             // dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
-            dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2, DRAG_BITMAP_PADDING / 2);
+            dragVisualizeOffset = new Point(-padding.get() / 2, padding.get() / 2);
             dragRect = new Rect(left, top, right, bottom);
         } else if (child instanceof FolderIcon) {
             int previewSize = grid.folderIconSizePx;
@@ -2606,7 +2698,7 @@
         // Clear the pressed state if necessary
         if (child instanceof BubbleTextView) {
             BubbleTextView icon = (BubbleTextView) child;
-            icon.clearPressedOrFocusedBackground();
+            icon.clearPressedBackground();
         }
 
         if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) {
@@ -2627,6 +2719,53 @@
         b.recycle();
     }
 
+    public void beginExternalDragShared(View child, DragSource source) {
+        LauncherAppState app = LauncherAppState.getInstance();
+        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+        int iconSize = grid.iconSizePx;
+
+        // Notify launcher of drag start
+        mLauncher.onDragStarted(child);
+
+        // Compose a new drag bitmap that is of the icon size
+        AtomicInteger padding = new AtomicInteger(DRAG_BITMAP_PADDING);
+        final Bitmap tmpB = createDragBitmap(child, padding);
+        Bitmap b = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
+        Paint p = new Paint();
+        p.setFilterBitmap(true);
+        mCanvas.setBitmap(b);
+        mCanvas.drawBitmap(tmpB, new Rect(0, 0, tmpB.getWidth(), tmpB.getHeight()),
+                new Rect(0, 0, iconSize, iconSize), p);
+        mCanvas.setBitmap(null);
+
+        // Find the child's location on the screen
+        int bmpWidth = tmpB.getWidth();
+        float iconScale = (float) bmpWidth / iconSize;
+        float scale = mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY) * iconScale;
+        int dragLayerX = Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);
+        int dragLayerY = Math.round(mTempXY[1]);
+
+        // Note: The drag region is used to calculate drag layer offsets, but the
+        // dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
+        Point dragVisualizeOffset = new Point(-padding.get() / 2, padding.get() / 2);
+        Rect dragRect = new Rect(0, 0, iconSize, iconSize);
+
+        if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) {
+            String msg = "Drag started with a view that has no tag set. This "
+                    + "will cause a crash (issue 11627249) down the line. "
+                    + "View: " + child + "  tag: " + child.getTag();
+            throw new IllegalStateException(msg);
+        }
+
+        // Start the drag
+        DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
+                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
+        dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
+
+        // Recycle temporary bitmaps
+        tmpB.recycle();
+    }
+
     void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, long screenId,
             int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
         View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
@@ -2640,7 +2779,8 @@
     }
 
     public boolean transitionStateShouldAllowDrop() {
-        return ((!isSwitchingState() || mTransitionProgress > 0.5f) && mState != State.SMALL);
+        return ((!isSwitchingState() || mTransitionProgress > 0.5f) &&
+                (mState == State.NORMAL || mState == State.SPRING_LOADED));
     }
 
     /**
@@ -2690,12 +2830,13 @@
                     mTargetCell);
             float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
                     mDragViewVisualCenter[1], mTargetCell);
-            if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
-                    mTargetCell, distance, true)) {
+            if (mCreateUserFolderOnDrop && willCreateUserFolder((ItemInfo) d.dragInfo,
+                    dropTargetLayout, mTargetCell, distance, true)) {
                 return true;
             }
-            if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
-                    mTargetCell, distance)) {
+
+            if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder((ItemInfo) d.dragInfo,
+                    dropTargetLayout, mTargetCell, distance)) {
                 return true;
             }
 
@@ -2905,13 +3046,11 @@
                 // cell also contains a shortcut, then create a folder with the two shortcuts.
                 if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
                         dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {
-                    removeExtraEmptyScreen(true, null, 0, true);
                     return;
                 }
 
                 if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
                         distance, d, false)) {
-                    removeExtraEmptyScreen(true, null, 0, true);
                     return;
                 }
 
@@ -2952,7 +3091,12 @@
                     final ItemInfo info = (ItemInfo) cell.getTag();
                     if (hasMovedLayouts) {
                         // Reparent the view
-                        getParentCellLayoutForView(cell).removeView(cell);
+                        CellLayout parentCell = getParentCellLayoutForView(cell);
+                        if (parentCell != null) {
+                            parentCell.removeView(cell);
+                        } else if (LauncherAppState.isDogfoodBuild()) {
+                            throw new NullPointerException("mDragInfo.cell has null parent");
+                        }
                         addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],
                                 info.spanX, info.spanY);
                     }
@@ -3017,7 +3161,6 @@
                     if (finalResizeRunnable != null) {
                         finalResizeRunnable.run();
                     }
-                    removeExtraEmptyScreen(true, null, 0, true);
                 }
             };
             mAnimatingViewIntoPlace = true;
@@ -3086,10 +3229,8 @@
         setCurrentDropLayout(layout);
         setCurrentDragOverlappingLayout(layout);
 
-        // Because we don't have space in the Phone UI (the CellLayouts run to the edge) we
-        // don't need to show the outlines
-        if (LauncherAppState.getInstance().isScreenLarge()) {
-            showOutlines();
+        if (!workspaceInModalState()) {
+            mLauncher.getDragLayer().showPageHints();
         }
     }
 
@@ -3099,7 +3240,6 @@
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
 
-        Resources res = launcher.getResources();
         Display display = launcher.getWindowManager().getDefaultDisplay();
         Point smallestSize = new Point();
         Point largestSize = new Point();
@@ -3165,6 +3305,7 @@
         if (!mIsPageMoving) {
             hideOutlines();
         }
+        mLauncher.getDragLayer().hidePageHints();
     }
 
     void setCurrentDropLayout(CellLayout layout) {
@@ -3407,11 +3548,17 @@
 
     public void onDragOver(DragObject d) {
         // Skip drag over events while we are dragging over side pages
-        if (mInScrollArea || mIsSwitchingState || mState == State.SMALL) return;
+        if (mInScrollArea || !transitionStateShouldAllowDrop()) return;
 
         Rect r = new Rect();
         CellLayout layout = null;
         ItemInfo item = (ItemInfo) d.dragInfo;
+        if (item == null) {
+            if (LauncherAppState.isDogfoodBuild()) {
+                throw new NullPointerException("DragObject has null info");
+            }
+            return;
+        }
 
         // Ensure that we have proper spans for the item that we are dropping
         if (item.spanX < 0 || item.spanY < 0) throw new RuntimeException("Improper spans found");
@@ -3420,7 +3567,7 @@
 
         final View child = (mDragInfo == null) ? null : mDragInfo.cell;
         // Identify whether we have dragged over a side page
-        if (isSmall()) {
+        if (workspaceInModalState()) {
             if (mLauncher.getHotseat() != null && !isExternalDragWidget(d)) {
                 if (isPointInSelfOverHotseat(d.x, d.y, r)) {
                     layout = mLauncher.getHotseat().getLayout();
@@ -3671,13 +3818,8 @@
         final Runnable exitSpringLoadedRunnable = new Runnable() {
             @Override
             public void run() {
-                removeExtraEmptyScreen(false, new Runnable() {
-                    @Override
-                    public void run() {
-                        mLauncher.exitSpringLoadedDragModeDelayed(true,
-                                Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
-                    }
-                });
+                mLauncher.exitSpringLoadedDragModeDelayed(true,
+                        Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
             }
         };
 
@@ -3739,6 +3881,11 @@
             Runnable onAnimationCompleteRunnable = new Runnable() {
                 @Override
                 public void run() {
+                    // Normally removeExtraEmptyScreen is called in Workspace#onDragEnd, but when
+                    // adding an item that may not be dropped right away (due to a config activity)
+                    // we defer the removal until the activity returns.
+                    deferRemoveExtraEmptyScreen();
+
                     // When dragging and dropping from customization tray, we deal with creating
                     // widgets/shortcuts/folders in a slightly different way
                     switch (pendingInfo.itemType) {
@@ -3823,15 +3970,16 @@
             } else {
                 cellLayout.findCellForSpan(mTargetCell, 1, 1);
             }
+            // Add the item to DB before adding to screen ensures that the container and other
+            // values of the info is properly updated.
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId,
+                    mTargetCell[0], mTargetCell[1]);
+
             addInScreen(view, container, screenId, mTargetCell[0], mTargetCell[1], info.spanX,
                     info.spanY, insertAtFirst);
             cellLayout.onDropChild(view);
-            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
             cellLayout.getShortcutsAndWidgets().measureChild(view);
 
-            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId,
-                    lp.cellX, lp.cellY);
-
             if (d.dragView != null) {
                 // We wrap the animation call in the temporary set and reset of the current
                 // cellLayout to its final transform -- this means we animate the drag view to
@@ -3854,12 +4002,12 @@
         int height = MeasureSpec.makeMeasureSpec(unScaledSize[1], MeasureSpec.EXACTLY);
         Bitmap b = Bitmap.createBitmap(unScaledSize[0], unScaledSize[1],
                 Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas(b);
+        mCanvas.setBitmap(b);
 
         layout.measure(width, height);
         layout.layout(0, 0, unScaledSize[0], unScaledSize[1]);
-        layout.draw(c);
-        c.setBitmap(null);
+        layout.draw(mCanvas);
+        mCanvas.setBitmap(null);
         layout.setVisibility(visibility);
         return b;
     }
@@ -4035,14 +4183,12 @@
                 CellLayout parentCell = getParentCellLayoutForView(mDragInfo.cell);
                 if (parentCell != null) {
                     parentCell.removeView(mDragInfo.cell);
+                } else if (LauncherAppState.isDogfoodBuild()) {
+                    throw new NullPointerException("mDragInfo.cell has null parent");
                 }
                 if (mDragInfo.cell instanceof DropTarget) {
                     mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
                 }
-                // If we move the item to anything not on the Workspace, check if any empty
-                // screens need to be removed. If we dropped back on the workspace, this will
-                // be done post drop animation.
-                removeExtraEmptyScreen(true, null, 0, true);
             }
         } else if (mDragInfo != null) {
             CellLayout cellLayout;
@@ -4051,7 +4197,13 @@
             } else {
                 cellLayout = getScreenWithId(mDragInfo.screenId);
             }
-            cellLayout.onDropChild(mDragInfo.cell);
+            if (cellLayout == null && LauncherAppState.isDogfoodBuild()) {
+                throw new RuntimeException("Invalid state: cellLayout == null in "
+                        + "Workspace#onDropCompleted. Please file a bug. ");
+            }
+            if (cellLayout != null) {
+                cellLayout.onDropChild(mDragInfo.cell);
+            }
         }
         if ((d.cancelled || (beingCalledAfterUninstall && !mUninstallSuccessful))
                 && mDragInfo.cell != null) {
@@ -4292,7 +4444,7 @@
 
     @Override
     public void scrollLeft() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             super.scrollLeft();
         }
         Folder openFolder = getOpenFolder();
@@ -4303,7 +4455,7 @@
 
     @Override
     public void scrollRight() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             super.scrollRight();
         }
         Folder openFolder = getOpenFolder();
@@ -4325,7 +4477,7 @@
         }
 
         boolean result = false;
-        if (!isSmall() && !mIsSwitchingState && getOpenFolder() == null) {
+        if (!workspaceInModalState() && !mIsSwitchingState && getOpenFolder() == null) {
             mInScrollArea = true;
 
             final int page = getNextPage() +
@@ -4417,57 +4569,70 @@
         return childrenLayouts;
     }
 
-    public Folder getFolderForTag(Object tag) {
-        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
-                getAllShortcutAndWidgetContainers();
-        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
-            int count = layout.getChildCount();
-            for (int i = 0; i < count; i++) {
-                View child = layout.getChildAt(i);
-                if (child instanceof Folder) {
-                    Folder f = (Folder) child;
-                    if (f.getInfo() == tag && f.getInfo().opened) {
-                        return f;
-                    }
-                }
+    public Folder getFolderForTag(final Object tag) {
+        return (Folder) getFirstMatch(new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                return (v instanceof Folder) && (((Folder) v).getInfo() == tag)
+                        && ((Folder) v).getInfo().opened;
             }
-        }
-        return null;
+        });
     }
 
-    public View getViewForTag(Object tag) {
-        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
-                getAllShortcutAndWidgetContainers();
-        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
-            int count = layout.getChildCount();
-            for (int i = 0; i < count; i++) {
-                View child = layout.getChildAt(i);
-                if (child.getTag() == tag) {
-                    return child;
-                }
+    public View getViewForTag(final Object tag) {
+        return getFirstMatch(new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                return info == tag;
             }
-        }
-        return null;
+        });
+    }
+
+    public LauncherAppWidgetHostView getWidgetForAppWidgetId(final int appWidgetId) {
+        return (LauncherAppWidgetHostView) getFirstMatch(new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                return (info instanceof LauncherAppWidgetInfo) &&
+                        ((LauncherAppWidgetInfo) info).appWidgetId == appWidgetId;
+            }
+        });
+    }
+
+    private View getFirstMatch(final ItemOperator operator) {
+        final View[] value = new View[1];
+        mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                if (operator.evaluate(info, v, parent)) {
+                    value[0] = v;
+                    return true;
+                }
+                return false;
+            }
+        });
+        return value[0];
     }
 
     void clearDropTargets() {
-        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
-                getAllShortcutAndWidgetContainers();
-        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
-            int childCount = layout.getChildCount();
-            for (int j = 0; j < childCount; j++) {
-                View v = layout.getChildAt(j);
+        mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
                 if (v instanceof DropTarget) {
                     mDragController.removeDropTarget((DropTarget) v);
                 }
+                // not done, process all the shortcuts
+                return false;
             }
-        }
+        });
     }
 
     // Removes ALL items that match a given package name, this is usually called when a package
     // has been removed and we want to remove all components (widgets, shortcuts, apps) that
     // belong to that package.
-    void removeItemsByPackageName(final ArrayList<String> packages) {
+    void removeItemsByPackageName(final ArrayList<String> packages, final UserHandleCompat user) {
         final HashSet<String> packageNames = new HashSet<String>();
         packageNames.addAll(packages);
 
@@ -4487,7 +4652,8 @@
             @Override
             public boolean filterItem(ItemInfo parent, ItemInfo info,
                                       ComponentName cn) {
-                if (packageNames.contains(cn.getPackageName())) {
+                if (packageNames.contains(cn.getPackageName())
+                        && info.user.equals(user)) {
                     cns.add(cn);
                     return true;
                 }
@@ -4497,13 +4663,13 @@
         LauncherModel.filterItemInfos(infos, filter);
 
         // Remove the affected components
-        removeItemsByComponentName(cns);
+        removeItemsByComponentName(cns, user);
     }
 
     // Removes items that match the application info specified, when applications are removed
     // as a part of an update, this is called to ensure that other widgets and application
     // shortcuts are not removed.
-    void removeItemsByApplicationInfo(final ArrayList<AppInfo> appInfos) {
+    void removeItemsByApplicationInfo(final ArrayList<AppInfo> appInfos, UserHandleCompat user) {
         // Just create a hash table of all the specific components that this will affect
         HashSet<ComponentName> cns = new HashSet<ComponentName>();
         for (AppInfo info : appInfos) {
@@ -4511,10 +4677,11 @@
         }
 
         // Remove all the things
-        removeItemsByComponentName(cns);
+        removeItemsByComponentName(cns, user);
     }
 
-    void removeItemsByComponentName(final HashSet<ComponentName> componentNames) {
+    void removeItemsByComponentName(final HashSet<ComponentName> componentNames,
+            final UserHandleCompat user) {
         ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
         for (final CellLayout layoutParent: cellLayouts) {
             final ViewGroup layout = layoutParent.getShortcutsAndWidgets();
@@ -4533,7 +4700,7 @@
                 public boolean filterItem(ItemInfo parent, ItemInfo info,
                                           ComponentName cn) {
                     if (parent instanceof FolderInfo) {
-                        if (componentNames.contains(cn)) {
+                        if (componentNames.contains(cn) && info.user.equals(user)) {
                             FolderInfo folder = (FolderInfo) parent;
                             ArrayList<ShortcutInfo> appsToRemove;
                             if (folderAppsToRemove.containsKey(folder)) {
@@ -4546,7 +4713,7 @@
                             return true;
                         }
                     } else {
-                        if (componentNames.contains(cn)) {
+                        if (componentNames.contains(cn) && info.user.equals(user)) {
                             childrenToRemove.add(children.get(info));
                             return true;
                         }
@@ -4584,52 +4751,290 @@
         stripEmptyScreens();
     }
 
-    private void updateShortcut(HashMap<ComponentName, AppInfo> appsMap, ItemInfo info,
-                                View child) {
-        ComponentName cn = info.getIntent().getComponent();
-        if (cn != null) {
-            AppInfo appInfo = appsMap.get(info.getIntent().getComponent());
-            if ((appInfo != null) && LauncherModel.isShortcutInfoUpdateable(info)) {
-                ShortcutInfo shortcutInfo = (ShortcutInfo) info;
-                BubbleTextView shortcut = (BubbleTextView) child;
-                shortcutInfo.updateIcon(mIconCache);
-                shortcutInfo.title = appInfo.title.toString();
-                shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache);
-            }
-        }
+    interface ItemOperator {
+        /**
+         * Process the next itemInfo, possibly with side-effect on {@link ItemOperator#value}.
+         *
+         * @param info info for the shortcut
+         * @param view view for the shortcut
+         * @param parent containing folder, or null
+         * @return true if done, false to continue the map
+         */
+        public boolean evaluate(ItemInfo info, View view, View parent);
     }
 
-    void updateShortcuts(ArrayList<AppInfo> apps) {
-        // Create a map of the apps to test against
-        final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
-        for (AppInfo ai : apps) {
-            appsMap.put(ai.componentName, ai);
-        }
-
-        ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
-        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
-            // Update all the children shortcuts
-            final HashMap<ItemInfo, View> children = new HashMap<ItemInfo, View>();
-            for (int j = 0; j < layout.getChildCount(); j++) {
-                View v = layout.getChildAt(j);
-                ItemInfo info = (ItemInfo) v.getTag();
-                if (info instanceof FolderInfo && v instanceof FolderIcon) {
-                    FolderIcon folder = (FolderIcon) v;
+    /**
+     * Map the operator over the shortcuts and widgets, return the first-non-null value.
+     *
+     * @param recurse true: iterate over folder children. false: op get the folders themselves.
+     * @param op the operator to map over the shortcuts
+     */
+    void mapOverItems(boolean recurse, ItemOperator op) {
+        ArrayList<ShortcutAndWidgetContainer> containers = getAllShortcutAndWidgetContainers();
+        final int containerCount = containers.size();
+        for (int containerIdx = 0; containerIdx < containerCount; containerIdx++) {
+            ShortcutAndWidgetContainer container = containers.get(containerIdx);
+            // map over all the shortcuts on the workspace
+            final int itemCount = container.getChildCount();
+            for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
+                View item = container.getChildAt(itemIdx);
+                ItemInfo info = (ItemInfo) item.getTag();
+                if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) {
+                    FolderIcon folder = (FolderIcon) item;
                     ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
-                    for (View fv : folderChildren) {
-                        info = (ItemInfo) fv.getTag();
-                        updateShortcut(appsMap, info, fv);
+                    // map over all the children in the folder
+                    final int childCount = folderChildren.size();
+                    for (int childIdx = 0; childIdx < childCount; childIdx++) {
+                        View child = folderChildren.get(childIdx);
+                        info = (ItemInfo) child.getTag();
+                        if (op.evaluate(info, child, folder)) {
+                            return;
+                        }
                     }
-                    folder.invalidate();
-                } else if (info instanceof ShortcutInfo) {
-                    updateShortcut(appsMap, info, v);
+                } else {
+                    if (op.evaluate(info, item, null)) {
+                        return;
+                    }
                 }
             }
         }
     }
 
+    void updateShortcutsAndWidgets(ArrayList<AppInfo> apps) {
+        // Break the appinfo list per user
+        final HashMap<UserHandleCompat, ArrayList<AppInfo>> appsPerUser =
+                new HashMap<UserHandleCompat, ArrayList<AppInfo>>();
+        for (AppInfo info : apps) {
+            ArrayList<AppInfo> filtered = appsPerUser.get(info.user);
+            if (filtered == null) {
+                filtered = new ArrayList<AppInfo>();
+                appsPerUser.put(info.user, filtered);
+            }
+            filtered.add(info);
+        }
+
+        for (Map.Entry<UserHandleCompat, ArrayList<AppInfo>> entry : appsPerUser.entrySet()) {
+            updateShortcutsAndWidgetsPerUser(entry.getValue(), entry.getKey());
+        }
+    }
+
+    private void updateShortcutsAndWidgetsPerUser(ArrayList<AppInfo> apps,
+            final UserHandleCompat user) {
+        // Create a map of the apps to test against
+        final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
+        final HashSet<String> pkgNames = new HashSet<String>();
+        for (AppInfo ai : apps) {
+            appsMap.put(ai.componentName, ai);
+            pkgNames.add(ai.componentName.getPackageName());
+        }
+        final HashSet<ComponentName> iconsToRemove = new HashSet<ComponentName>();
+
+        mapOverItems(MAP_RECURSE, new ItemOperator() {
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+                    ComponentName cn = shortcutInfo.getTargetComponent();
+                    AppInfo appInfo = appsMap.get(cn);
+                    if (user.equals(shortcutInfo.user) && cn != null
+                            && LauncherModel.isShortcutInfoUpdateable(info)
+                            && pkgNames.contains(cn.getPackageName())) {
+                        boolean promiseStateChanged = false;
+                        boolean infoUpdated = false;
+                        if (shortcutInfo.isPromise()) {
+                            if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+                                // Auto install icon
+                                PackageManager pm = getContext().getPackageManager();
+                                ResolveInfo matched = pm.resolveActivity(
+                                        new Intent(Intent.ACTION_MAIN)
+                                        .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
+                                        PackageManager.MATCH_DEFAULT_ONLY);
+                                if (matched == null) {
+                                    // Try to find the best match activity.
+                                    Intent intent = pm.getLaunchIntentForPackage(
+                                            cn.getPackageName());
+                                    if (intent != null) {
+                                        cn = intent.getComponent();
+                                        appInfo = appsMap.get(cn);
+                                    }
+
+                                    if ((intent == null) || (appsMap == null)) {
+                                        // Could not find a default activity. Remove this item.
+                                        iconsToRemove.add(shortcutInfo.getTargetComponent());
+
+                                        // process next shortcut.
+                                        return false;
+                                    }
+                                    shortcutInfo.promisedIntent = intent;
+                                }
+                            }
+
+                            // Restore the shortcut.
+                            shortcutInfo.intent = shortcutInfo.promisedIntent;
+                            shortcutInfo.promisedIntent = null;
+                            shortcutInfo.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
+                                    & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
+                                    & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+
+                            promiseStateChanged = true;
+                            infoUpdated = true;
+                            shortcutInfo.updateIcon(mIconCache);
+                            LauncherModel.updateItemInDatabase(getContext(), shortcutInfo);
+                        }
+
+
+                        if (appInfo != null) {
+                            shortcutInfo.updateIcon(mIconCache);
+                            shortcutInfo.title = appInfo.title.toString();
+                            shortcutInfo.contentDescription = appInfo.contentDescription;
+                            infoUpdated = true;
+                        }
+
+                        if (infoUpdated) {
+                            BubbleTextView shortcut = (BubbleTextView) v;
+                            shortcut.applyFromShortcutInfo(shortcutInfo,
+                                    mIconCache, true, promiseStateChanged);
+
+                            if (parent != null) {
+                                parent.invalidate();
+                            }
+                        }
+                    }
+                }
+                // process all the shortcuts
+                return false;
+            }
+        });
+
+        if (!iconsToRemove.isEmpty()) {
+            removeItemsByComponentName(iconsToRemove, user);
+        }
+        if (user.equals(UserHandleCompat.myUserHandle())) {
+            restorePendingWidgets(pkgNames);
+        }
+    }
+
+    public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
+        ArrayList<String> packages = new ArrayList<String>(1);
+        packages.add(packageName);
+        LauncherModel.deletePackageFromDatabase(mLauncher, packageName, user);
+        removeItemsByPackageName(packages, user);
+    }
+
+    public void updatePackageBadge(final String packageName, final UserHandleCompat user) {
+        mapOverItems(MAP_RECURSE, new ItemOperator() {
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+                    ComponentName cn = shortcutInfo.getTargetComponent();
+                    if (user.equals(shortcutInfo.user) && cn != null
+                            && shortcutInfo.isPromise()
+                            && packageName.equals(cn.getPackageName())) {
+                        if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+                            // For auto install apps update the icon as well as label.
+                            mIconCache.getTitleAndIcon(shortcutInfo,
+                                    shortcutInfo.promisedIntent, user, true);
+                        } else {
+                            // Only update the icon for restored apps.
+                            shortcutInfo.updateIcon(mIconCache);
+                        }
+                        BubbleTextView shortcut = (BubbleTextView) v;
+                        shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
+
+                        if (parent != null) {
+                            parent.invalidate();
+                        }
+                    }
+                }
+                // process all the shortcuts
+                return false;
+            }
+        });
+    }
+
+    public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) {
+        HashSet<String> completedPackages = new HashSet<String>();
+
+        for (final PackageInstallInfo installInfo : installInfos) {
+            mapOverItems(MAP_RECURSE, new ItemOperator() {
+                @Override
+                public boolean evaluate(ItemInfo info, View v, View parent) {
+                    if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+                        ShortcutInfo si = (ShortcutInfo) info;
+                        ComponentName cn = si.getTargetComponent();
+                        if (si.isPromise() && (cn != null)
+                                && installInfo.packageName.equals(cn.getPackageName())) {
+                            si.setInstallProgress(installInfo.progress);
+                            if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) {
+                                // Mark this info as broken.
+                                si.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+                            }
+                            ((BubbleTextView)v).applyState(false);
+                        }
+                    } else if (v instanceof PendingAppWidgetHostView
+                            && info instanceof LauncherAppWidgetInfo
+                            && ((LauncherAppWidgetInfo) info).providerName.getPackageName()
+                                .equals(installInfo.packageName)) {
+                        ((LauncherAppWidgetInfo) info).installProgress = installInfo.progress;
+                        ((PendingAppWidgetHostView) v).applyState();
+                    }
+
+                    // process all the shortcuts
+                    return false;
+                }
+            });
+
+            if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
+                completedPackages.add(installInfo.packageName);
+            }
+        }
+
+        // Note that package states are sent only for myUser
+        if (!completedPackages.isEmpty()) {
+            restorePendingWidgets(completedPackages);
+        }
+    }
+
+    private void restorePendingWidgets(final Set<String> installedPackaged) {
+        final ArrayList<LauncherAppWidgetInfo> changedInfo = new ArrayList<LauncherAppWidgetInfo>();
+
+        // Iterate non recursively as widgets can't be inside a folder.
+        mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                if (info instanceof LauncherAppWidgetInfo) {
+                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
+                    if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
+                            && installedPackaged.contains(widgetInfo.providerName.getPackageName())) {
+
+                        changedInfo.add(widgetInfo);
+
+                        // Remove the provider not ready flag
+                        widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+                        LauncherModel.updateItemInDatabase(getContext(), widgetInfo);
+                    }
+                }
+                // process all the widget
+                return false;
+            }
+        });
+        if (!changedInfo.isEmpty()) {
+            DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
+                    mLauncher.getAppWidgetHost());
+            if (LauncherModel.findAppWidgetProviderInfoWithComponent(getContext(),
+                    changedInfo.get(0).providerName) != null) {
+                // Re-inflate the widgets which have changed status
+                widgetRefresh.run();
+            } else {
+                // widgetRefresh will automatically run when the packages are updated.
+            }
+        }
+    }
+
     private void moveToScreen(int page, boolean animate) {
-        if (!isSmall()) {
+        if (!workspaceInModalState()) {
             if (animate) {
                 snapToPage(page);
             } else {
@@ -4702,4 +5107,53 @@
     public void getLocationInDragLayer(int[] loc) {
         mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
     }
+
+    /**
+     * Used as a workaround to ensure that the AppWidgetService receives the
+     * PACKAGE_ADDED broadcast before updating widgets.
+     */
+    private class DeferredWidgetRefresh implements Runnable {
+        private final ArrayList<LauncherAppWidgetInfo> mInfos;
+        private final LauncherAppWidgetHost mHost;
+        private final Handler mHandler;
+
+        private boolean mRefreshPending;
+
+        public DeferredWidgetRefresh(ArrayList<LauncherAppWidgetInfo> infos,
+                LauncherAppWidgetHost host) {
+            mInfos = infos;
+            mHost = host;
+            mHandler = new Handler();
+            mRefreshPending = true;
+
+            mHost.addProviderChangeListener(this);
+            // Force refresh after 10 seconds, if we don't get the provider changed event.
+            // This could happen when the provider is no longer available in the app.
+            mHandler.postDelayed(this, 10000);
+        }
+
+        @Override
+        public void run() {
+            mHost.removeProviderChangeListener(this);
+            mHandler.removeCallbacks(this);
+
+            if (!mRefreshPending) {
+                return;
+            }
+
+            mRefreshPending = false;
+
+            for (LauncherAppWidgetInfo info : mInfos) {
+                if (info.hostView instanceof PendingAppWidgetHostView) {
+                    PendingAppWidgetHostView view = (PendingAppWidgetHostView) info.hostView;
+                    mLauncher.removeAppWidget(info);
+
+                    CellLayout cl = (CellLayout) view.getParent().getParent();
+                    // Remove the current widget
+                    cl.removeView(view);
+                    mLauncher.bindAppWidget(info);
+                }
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
new file mode 100644
index 0000000..6512d42
--- /dev/null
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+
+import com.android.launcher3.IconCache;
+import com.android.launcher3.Utilities;
+
+import java.util.List;
+
+public abstract class AppWidgetManagerCompat {
+
+    private static final Object sInstanceLock = new Object();
+    private static AppWidgetManagerCompat sInstance;
+
+
+    public static AppWidgetManagerCompat getInstance(Context context) {
+        synchronized (sInstanceLock) {
+            if (sInstance == null) {
+                if (Utilities.isLmpOrAbove()) {
+                    sInstance = new AppWidgetManagerCompatVL(context.getApplicationContext());
+                } else {
+                    sInstance = new AppWidgetManagerCompatV16(context.getApplicationContext());
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    final AppWidgetManager mAppWidgetManager;
+    final Context mContext;
+
+    AppWidgetManagerCompat(Context context) {
+        mContext = context;
+        mAppWidgetManager = AppWidgetManager.getInstance(context);
+    }
+
+    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
+        return mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+    }
+
+    public abstract List<AppWidgetProviderInfo> getAllProviders();
+
+    public abstract String loadLabel(AppWidgetProviderInfo info);
+
+    public abstract boolean bindAppWidgetIdIfAllowed(
+            int appWidgetId, AppWidgetProviderInfo info, Bundle options);
+
+    public abstract UserHandleCompat getUser(AppWidgetProviderInfo info);
+
+    public abstract void startConfigActivity(AppWidgetProviderInfo info, int widgetId,
+            Activity activity, AppWidgetHost host, int requestCode);
+
+    public abstract Drawable loadPreview(AppWidgetProviderInfo info);
+
+    public abstract Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache);
+
+    public abstract Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap);
+
+}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
new file mode 100644
index 0000000..f599f43
--- /dev/null
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+
+import com.android.launcher3.IconCache;
+import com.android.launcher3.Utilities;
+
+import java.util.List;
+
+class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
+
+    AppWidgetManagerCompatV16(Context context) {
+        super(context);
+    }
+
+    @Override
+    public List<AppWidgetProviderInfo> getAllProviders() {
+        return mAppWidgetManager.getInstalledProviders();
+    }
+
+    @Override
+    public String loadLabel(AppWidgetProviderInfo info) {
+        return info.label.trim();
+    }
+
+    @Override
+    public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
+            Bundle options) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider);
+        } else {
+            return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider, options);
+        }
+    }
+
+    @Override
+    public UserHandleCompat getUser(AppWidgetProviderInfo info) {
+        return UserHandleCompat.myUserHandle();
+    }
+
+    @Override
+    public void startConfigActivity(AppWidgetProviderInfo info, int widgetId, Activity activity,
+            AppWidgetHost host, int requestCode) {
+        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+        intent.setComponent(info.configure);
+        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
+        Utilities.startActivityForResultSafely(activity, intent, requestCode);
+    }
+
+    @Override
+    public Drawable loadPreview(AppWidgetProviderInfo info) {
+        return mContext.getPackageManager().getDrawable(
+                info.provider.getPackageName(), info.previewImage, null);
+    }
+
+    @Override
+    public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
+        return cache.getFullResIcon(info.provider.getPackageName(), info.icon);
+    }
+
+    @Override
+    public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
+        return bitmap;
+    }
+}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
new file mode 100644
index 0000000..c3853ab
--- /dev/null
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.View;
+import android.widget.Toast;
+
+import com.android.launcher3.IconCache;
+import com.android.launcher3.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@TargetApi(Build.VERSION_CODES.L)
+class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
+
+    private final UserManager mUserManager;
+    private final PackageManager mPm;
+
+    AppWidgetManagerCompatVL(Context context) {
+        super(context);
+        mPm = context.getPackageManager();
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    @Override
+    public List<AppWidgetProviderInfo> getAllProviders() {
+        ArrayList<AppWidgetProviderInfo> providers = new ArrayList<AppWidgetProviderInfo>();
+        for (UserHandle user : mUserManager.getUserProfiles()) {
+            providers.addAll(mAppWidgetManager.getInstalledProvidersForProfile(user));
+        }
+        return providers;
+    }
+
+    @Override
+    public String loadLabel(AppWidgetProviderInfo info) {
+        return info.loadLabel(mPm);
+    }
+
+    @Override
+    public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
+            Bundle options) {
+        return mAppWidgetManager.bindAppWidgetIdIfAllowed(
+                appWidgetId, info.getProfile(), info.provider, options);
+    }
+
+    @Override
+    public UserHandleCompat getUser(AppWidgetProviderInfo info) {
+        return UserHandleCompat.fromUser(info.getProfile());
+    }
+
+    @Override
+    public void startConfigActivity(AppWidgetProviderInfo info, int widgetId, Activity activity,
+            AppWidgetHost host, int requestCode) {
+        try {
+            host.startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode, null);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+        } catch (SecurityException e) {
+            Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    @Override
+    public Drawable loadPreview(AppWidgetProviderInfo info) {
+        return info.loadPreviewImage(mContext, 0);
+    }
+
+    @Override
+    public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
+        return info.loadIcon(mContext, cache.getFullResIconDpi());
+    }
+
+    @Override
+    public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
+        if (info.getProfile().equals(android.os.Process.myUserHandle())) {
+            return bitmap;
+        }
+
+        // Add a user badge in the bottom right of the image.
+        final Resources res = mContext.getResources();
+        final int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size);
+        final int badgeMargin = res.getDimensionPixelSize(R.dimen.profile_badge_margin);
+        final Rect badgeLocation = new Rect(0, 0, badgeSize, badgeSize);
+
+        final int top = bitmap.getHeight() - badgeSize - badgeMargin;
+        if (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+            badgeLocation.offset(badgeMargin, top);
+        } else {
+            badgeLocation.offset(bitmap.getWidth() - badgeSize - badgeMargin, top);
+        }
+
+        Drawable drawable = mPm.getUserBadgedDrawableForDensity(
+                new BitmapDrawable(res, bitmap), info.getProfile(), badgeLocation, 0);
+
+        if (drawable instanceof BitmapDrawable) {
+            return ((BitmapDrawable) drawable).getBitmap();
+        }
+
+        bitmap.eraseColor(Color.TRANSPARENT);
+        Canvas c = new Canvas(bitmap);
+        drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
+        drawable.draw(c);
+        c.setBitmap(null);
+        return bitmap;
+    }
+}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
new file mode 100644
index 0000000..90a4d1a
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.graphics.drawable.Drawable;
+
+public abstract class LauncherActivityInfoCompat {
+
+    LauncherActivityInfoCompat() {
+    }
+
+    public abstract ComponentName getComponentName();
+    public abstract UserHandleCompat getUser();
+    public abstract CharSequence getLabel();
+    public abstract Drawable getIcon(int density);
+    public abstract ApplicationInfo getApplicationInfo();
+    public abstract long getFirstInstallTime();
+    public abstract Drawable getBadgedIcon(int density);
+}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
new file mode 100644
index 0000000..1d41a6f
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+
+
+public class LauncherActivityInfoCompatV16 extends LauncherActivityInfoCompat {
+    private ActivityInfo mActivityInfo;
+    private ComponentName mComponentName;
+    private PackageManager mPm;
+
+    LauncherActivityInfoCompatV16(Context context, ResolveInfo info) {
+        super();
+        this.mActivityInfo = info.activityInfo;
+        mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
+        mPm = context.getPackageManager();
+    }
+
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    public UserHandleCompat getUser() {
+        return UserHandleCompat.myUserHandle();
+    }
+
+    public CharSequence getLabel() {
+        return mActivityInfo.loadLabel(mPm);
+    }
+
+    public Drawable getIcon(int density) {
+        Drawable d = null;
+        if (mActivityInfo.getIconResource() != 0) {
+            Resources resources;
+            try {
+                resources = mPm.getResourcesForApplication(mActivityInfo.packageName);
+            } catch (PackageManager.NameNotFoundException e) {
+                resources = null;
+            }
+            if (resources != null) {
+                try {
+                    d = resources.getDrawableForDensity(mActivityInfo.getIconResource(), density);
+                } catch (Resources.NotFoundException e) {
+                    // Return default icon below.
+                }
+            }
+        }
+        if (d == null) {
+            Resources resources = Resources.getSystem();
+            d = resources.getDrawableForDensity(android.R.mipmap.sym_def_app_icon, density);
+        }
+        return d;
+    }
+
+    public ApplicationInfo getApplicationInfo() {
+        return mActivityInfo.applicationInfo;
+    }
+
+    public long getFirstInstallTime() {
+        try {
+            PackageInfo info = mPm.getPackageInfo(mActivityInfo.packageName, 0);
+            return info != null ? info.firstInstallTime : 0;
+        } catch (NameNotFoundException e) {
+            return 0;
+        }
+    }
+
+    public String getName() {
+        return mActivityInfo.name;
+    }
+
+    public Drawable getBadgedIcon(int density) {
+        return getIcon(density);
+    }
+}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
new file mode 100644
index 0000000..b52cf1d
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+
+public class LauncherActivityInfoCompatVL extends LauncherActivityInfoCompat {
+    private LauncherActivityInfo mLauncherActivityInfo;
+
+    LauncherActivityInfoCompatVL(LauncherActivityInfo launcherActivityInfo) {
+        super();
+        mLauncherActivityInfo = launcherActivityInfo;
+    }
+
+    public ComponentName getComponentName() {
+        return mLauncherActivityInfo.getComponentName();
+    }
+
+    public UserHandleCompat getUser() {
+        return UserHandleCompat.fromUser(mLauncherActivityInfo.getUser());
+    }
+
+    public CharSequence getLabel() {
+        return mLauncherActivityInfo.getLabel();
+    }
+
+    public Drawable getIcon(int density) {
+        return mLauncherActivityInfo.getIcon(density);
+    }
+
+    public ApplicationInfo getApplicationInfo() {
+        return mLauncherActivityInfo.getApplicationInfo();
+    }
+
+    public long getFirstInstallTime() {
+        return mLauncherActivityInfo.getFirstInstallTime();
+    }
+
+    public Drawable getBadgedIcon(int density) {
+        return mLauncherActivityInfo.getBadgedIcon(density);
+    }
+}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
new file mode 100644
index 0000000..6efcc00
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Bundle;
+
+import com.android.launcher3.Utilities;
+
+import java.util.List;
+
+public abstract class LauncherAppsCompat {
+
+    public static final String ACTION_MANAGED_PROFILE_ADDED =
+            "android.intent.action.MANAGED_PROFILE_ADDED";
+    public static final String ACTION_MANAGED_PROFILE_REMOVED =
+            "android.intent.action.MANAGED_PROFILE_REMOVED";
+
+    public interface OnAppsChangedCallbackCompat {
+        void onPackageRemoved(String packageName, UserHandleCompat user);
+        void onPackageAdded(String packageName, UserHandleCompat user);
+        void onPackageChanged(String packageName, UserHandleCompat user);
+        void onPackagesAvailable(String[] packageNames, UserHandleCompat user, boolean replacing);
+        void onPackagesUnavailable(String[] packageNames, UserHandleCompat user, boolean replacing);
+    }
+
+    protected LauncherAppsCompat() {
+    }
+
+    private static LauncherAppsCompat sInstance;
+    private static Object sInstanceLock = new Object();
+
+    public static LauncherAppsCompat getInstance(Context context) {
+        synchronized (sInstanceLock) {
+            if (sInstance == null) {
+                if (Utilities.isLmpOrAbove()) {
+                    sInstance = new LauncherAppsCompatVL(context.getApplicationContext());
+                } else {
+                    sInstance = new LauncherAppsCompatV16(context.getApplicationContext());
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    public abstract List<LauncherActivityInfoCompat> getActivityList(String packageName,
+            UserHandleCompat user);
+    public abstract LauncherActivityInfoCompat resolveActivity(Intent intent,
+            UserHandleCompat user);
+    public abstract void startActivityForProfile(ComponentName component, UserHandleCompat user,
+            Rect sourceBounds, Bundle opts);
+    public abstract void showAppDetailsForProfile(ComponentName component, UserHandleCompat user);
+    public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
+    public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
+    public abstract boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user);
+    public abstract boolean isActivityEnabledForProfile(ComponentName component,
+            UserHandleCompat user);
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
new file mode 100644
index 0000000..7e5e6bf
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Version of {@link LauncherAppsCompat} for devices with API level 16.
+ * Devices Pre-L don't support multiple profiles in one launcher so
+ * user parameters are ignored and all methods operate on the current user.
+ */
+public class LauncherAppsCompatV16 extends LauncherAppsCompat {
+
+    private PackageManager mPm;
+    private Context mContext;
+    private List<OnAppsChangedCallbackCompat> mCallbacks
+            = new ArrayList<OnAppsChangedCallbackCompat>();
+    private PackageMonitor mPackageMonitor;
+
+    LauncherAppsCompatV16(Context context) {
+        mPm = context.getPackageManager();
+        mContext = context;
+        mPackageMonitor = new PackageMonitor();
+   }
+
+    public List<LauncherActivityInfoCompat> getActivityList(String packageName,
+            UserHandleCompat user) {
+        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        mainIntent.setPackage(packageName);
+        List<ResolveInfo> infos = mPm.queryIntentActivities(mainIntent, 0);
+        List<LauncherActivityInfoCompat> list =
+                new ArrayList<LauncherActivityInfoCompat>(infos.size());
+        for (ResolveInfo info : infos) {
+            list.add(new LauncherActivityInfoCompatV16(mContext, info));
+        }
+        return list;
+    }
+
+    public LauncherActivityInfoCompat resolveActivity(Intent intent, UserHandleCompat user) {
+        ResolveInfo info = mPm.resolveActivity(intent, 0);
+        if (info != null) {
+            return new LauncherActivityInfoCompatV16(mContext, info);
+        }
+        return null;
+    }
+
+    public void startActivityForProfile(ComponentName component, UserHandleCompat user,
+            Rect sourceBounds, Bundle opts) {
+        Intent launchIntent = new Intent(Intent.ACTION_MAIN);
+        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        launchIntent.setComponent(component);
+        launchIntent.setSourceBounds(sourceBounds);
+        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(launchIntent, opts);
+    }
+
+    public void showAppDetailsForProfile(ComponentName component, UserHandleCompat user) {
+        String packageName = component.getPackageName();
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                Uri.fromParts("package", packageName, null));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
+                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        mContext.startActivity(intent, null);
+    }
+
+    public synchronized void addOnAppsChangedCallback(OnAppsChangedCallbackCompat callback) {
+        if (callback != null && !mCallbacks.contains(callback)) {
+            mCallbacks.add(callback);
+            if (mCallbacks.size() == 1) {
+                registerForPackageIntents();
+            }
+        }
+    }
+
+    public synchronized void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat callback) {
+        mCallbacks.remove(callback);
+        if (mCallbacks.size() == 0) {
+            unregisterForPackageIntents();
+        }
+    }
+
+    public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
+        try {
+            PackageInfo info = mPm.getPackageInfo(packageName, 0);
+            return info != null && info.applicationInfo.enabled;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
+        try {
+            ActivityInfo info = mPm.getActivityInfo(component, 0);
+            return info != null && info.isEnabled();
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    private void unregisterForPackageIntents() {
+        mContext.unregisterReceiver(mPackageMonitor);
+    }
+
+    private void registerForPackageIntents() {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addDataScheme("package");
+        mContext.registerReceiver(mPackageMonitor, filter);
+        filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        mContext.registerReceiver(mPackageMonitor, filter);
+    }
+
+    private synchronized List<OnAppsChangedCallbackCompat> getCallbacks() {
+        return new ArrayList<OnAppsChangedCallbackCompat>(mCallbacks);
+    }
+
+    private class PackageMonitor extends BroadcastReceiver {
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final UserHandleCompat user = UserHandleCompat.myUserHandle();
+
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                    || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                    || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                final String packageName = intent.getData().getSchemeSpecificPart();
+                final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+                if (packageName == null || packageName.length() == 0) {
+                    // they sent us a bad intent
+                    return;
+                }
+                if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+                    for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                        callback.onPackageChanged(packageName, user);
+                    }
+                } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                    if (!replacing) {
+                        for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                            callback.onPackageRemoved(packageName, user);
+                        }
+                    }
+                    // else, we are replacing the package, so a PACKAGE_ADDED will be sent
+                    // later, we will update the package at this time
+                } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                    if (!replacing) {
+                        for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                            callback.onPackageAdded(packageName, user);
+                        }
+                    } else {
+                        for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                            callback.onPackageChanged(packageName, user);
+                        }
+                    }
+                }
+            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+                // EXTRA_REPLACING is available Kitkat onwards. For lower devices, it is broadcasted
+                // when moving a package or mounting/un-mounting external storage. Assume that
+                // it is a replacing operation.
+                final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING,
+                        Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT);
+                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                    callback.onPackagesAvailable(packages, user, replacing);
+                }
+            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+                final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING,
+                        Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT);
+                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
+                    callback.onPackagesUnavailable(packages, user, replacing);
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
new file mode 100644
index 0000000..e0d28b5
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class LauncherAppsCompatVL extends LauncherAppsCompat {
+
+    private LauncherApps mLauncherApps;
+
+    private Map<OnAppsChangedCallbackCompat, WrappedCallback> mCallbacks
+            = new HashMap<OnAppsChangedCallbackCompat, WrappedCallback>();
+
+    LauncherAppsCompatVL(Context context) {
+        super();
+        mLauncherApps = (LauncherApps) context.getSystemService("launcherapps");
+    }
+
+    public List<LauncherActivityInfoCompat> getActivityList(String packageName,
+            UserHandleCompat user) {
+        List<LauncherActivityInfo> list = mLauncherApps.getActivityList(packageName,
+                user.getUser());
+        if (list.size() == 0) {
+            return Collections.EMPTY_LIST;
+        }
+        ArrayList<LauncherActivityInfoCompat> compatList =
+                new ArrayList<LauncherActivityInfoCompat>(list.size());
+        for (LauncherActivityInfo info : list) {
+            compatList.add(new LauncherActivityInfoCompatVL(info));
+        }
+        return compatList;
+    }
+
+    public LauncherActivityInfoCompat resolveActivity(Intent intent, UserHandleCompat user) {
+        LauncherActivityInfo activity = mLauncherApps.resolveActivity(intent, user.getUser());
+        if (activity != null) {
+            return new LauncherActivityInfoCompatVL(activity);
+        } else {
+            return null;
+        }
+    }
+
+    public void startActivityForProfile(ComponentName component, UserHandleCompat user,
+            Rect sourceBounds, Bundle opts) {
+        mLauncherApps.startMainActivity(component, user.getUser(), sourceBounds, opts);
+    }
+
+    public void showAppDetailsForProfile(ComponentName component, UserHandleCompat user) {
+        mLauncherApps.startAppDetailsActivity(component, user.getUser(), null, null);
+    }
+
+    public void addOnAppsChangedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
+        WrappedCallback wrappedCallback = new WrappedCallback(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.put(callback, wrappedCallback);
+        }
+        mLauncherApps.registerCallback(wrappedCallback);
+    }
+
+    public void removeOnAppsChangedCallback(
+            LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
+        WrappedCallback wrappedCallback = null;
+        synchronized (mCallbacks) {
+            wrappedCallback = mCallbacks.remove(callback);
+        }
+        if (wrappedCallback != null) {
+            mLauncherApps.unregisterCallback(wrappedCallback);
+        }
+    }
+
+    public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
+        return mLauncherApps.isPackageEnabled(packageName, user.getUser());
+    }
+
+    public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
+        return mLauncherApps.isActivityEnabled(component, user.getUser());
+    }
+
+    private static class WrappedCallback extends LauncherApps.Callback {
+        private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
+
+        public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
+            mCallback = callback;
+        }
+
+        public void onPackageRemoved(String packageName, UserHandle user) {
+            mCallback.onPackageRemoved(packageName, UserHandleCompat.fromUser(user));
+        }
+
+        public void onPackageAdded(String packageName, UserHandle user) {
+            mCallback.onPackageAdded(packageName, UserHandleCompat.fromUser(user));
+        }
+
+        public void onPackageChanged(String packageName, UserHandle user) {
+            mCallback.onPackageChanged(packageName, UserHandleCompat.fromUser(user));
+        }
+
+        public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
+            mCallback.onPackagesAvailable(packageNames, UserHandleCompat.fromUser(user), replacing);
+        }
+
+        public void onPackagesUnavailable(String[] packageNames, UserHandle user,
+                boolean replacing) {
+            mCallback.onPackagesUnavailable(packageNames, UserHandleCompat.fromUser(user),
+                    replacing);
+        }
+    }
+}
+
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java
new file mode 100644
index 0000000..0eb8754
--- /dev/null
+++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+
+import com.android.launcher3.Utilities;
+
+import java.util.HashSet;
+
+public abstract class PackageInstallerCompat {
+
+    public static final int STATUS_INSTALLED = 0;
+    public static final int STATUS_INSTALLING = 1;
+    public static final int STATUS_FAILED = 2;
+
+    private static final Object sInstanceLock = new Object();
+    private static PackageInstallerCompat sInstance;
+
+    public static PackageInstallerCompat getInstance(Context context) {
+        synchronized (sInstanceLock) {
+            if (sInstance == null) {
+                if (Utilities.isLmpOrAbove()) {
+                    sInstance = new PackageInstallerCompatVL(context);
+                } else {
+                    sInstance = new PackageInstallerCompatV16(context) { };
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    public abstract HashSet<String> updateAndGetActiveSessionCache();
+
+    public abstract void onPause();
+
+    public abstract void onResume();
+
+    public abstract void onFinishBind();
+
+    public abstract void onStop();
+
+    public abstract void recordPackageUpdate(String packageName, int state, int progress);
+
+    public static final class PackageInstallInfo {
+        public final String packageName;
+
+        public int state;
+        public int progress;
+
+        public PackageInstallInfo(String packageName) {
+            this.packageName = packageName;
+        }
+
+        public PackageInstallInfo(String packageName, int state, int progress) {
+            this.packageName = packageName;
+            this.state = state;
+            this.progress = progress;
+        }
+    }
+}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
new file mode 100644
index 0000000..1910d22
--- /dev/null
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.LauncherAppState;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONStringer;
+import org.json.JSONTokener;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+public class PackageInstallerCompatV16 extends PackageInstallerCompat {
+
+    private static final String TAG = "PackageInstallerCompatV16";
+    private static final boolean DEBUG = false;
+
+    private static final String KEY_PROGRESS = "progress";
+    private static final String KEY_STATE = "state";
+
+    private static final String PREFS =
+            "com.android.launcher3.compat.PackageInstallerCompatV16.queue";
+
+    protected final SharedPreferences mPrefs;
+
+    boolean mUseQueue;
+    boolean mFinishedBind;
+    boolean mReplayPending;
+
+    PackageInstallerCompatV16(Context context) {
+        mPrefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
+    }
+
+    @Override
+    public void onPause() {
+        mUseQueue = true;
+        if (DEBUG) Log.d(TAG, "updates paused");
+    }
+
+    @Override
+    public void onResume() {
+        mUseQueue = false;
+        if (mFinishedBind) {
+            replayUpdates();
+        }
+    }
+
+    @Override
+    public void onFinishBind() {
+        mFinishedBind = true;
+        if (!mUseQueue) {
+            replayUpdates();
+        }
+    }
+
+    @Override
+    public void onStop() { }
+
+    private void replayUpdates() {
+        if (DEBUG) Log.d(TAG, "updates resumed");
+        LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+        if (app == null) {
+            mReplayPending = true; // try again later
+            if (DEBUG) Log.d(TAG, "app is null, delaying send");
+            return;
+        }
+        mReplayPending = false;
+        ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
+        for (String packageName: mPrefs.getAll().keySet()) {
+            final String json = mPrefs.getString(packageName, null);
+            if (!TextUtils.isEmpty(json)) {
+                updates.add(infoFromJson(packageName, json));
+            }
+        }
+        if (!updates.isEmpty()) {
+            sendUpdate(app, updates);
+        }
+    }
+
+    /**
+     * This should be called by the implementations to register a package update.
+     */
+    @Override
+    public synchronized void recordPackageUpdate(String packageName, int state, int progress) {
+        SharedPreferences.Editor editor = mPrefs.edit();
+        PackageInstallInfo installInfo = new PackageInstallInfo(packageName);
+        installInfo.progress = progress;
+        installInfo.state = state;
+        if (state == STATUS_INSTALLED) {
+            // no longer necessary to track this package
+            editor.remove(packageName);
+            if (DEBUG) Log.d(TAG, "no longer tracking " + packageName);
+        } else {
+            editor.putString(packageName, infoToJson(installInfo));
+            if (DEBUG)
+                Log.d(TAG, "saved state: " + infoToJson(installInfo)
+                        + " for package: " + packageName);
+
+        }
+        editor.commit();
+
+        if (!mUseQueue) {
+            if (mReplayPending) {
+                replayUpdates();
+            } else if (state != STATUS_INSTALLED) {
+                LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+                ArrayList<PackageInstallInfo> update = new ArrayList<PackageInstallInfo>();
+                update.add(installInfo);
+                sendUpdate(app, update);
+            }
+        }
+    }
+
+    private void sendUpdate(LauncherAppState app, ArrayList<PackageInstallInfo> updates) {
+        if (app == null) {
+            mReplayPending = true; // try again later
+            if (DEBUG) Log.d(TAG, "app is null, delaying send");
+        } else {
+            app.setPackageState(updates);
+        }
+    }
+
+    private static PackageInstallInfo infoFromJson(String packageName, String json) {
+        PackageInstallInfo info = new PackageInstallInfo(packageName);
+        try {
+            JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
+            info.state = object.getInt(KEY_STATE);
+            info.progress = object.getInt(KEY_PROGRESS);
+        } catch (JSONException e) {
+            Log.e(TAG, "failed to deserialize app state update", e);
+        }
+        return info;
+    }
+
+    private static String infoToJson(PackageInstallInfo info) {
+        String value = null;
+        try {
+            JSONStringer json = new JSONStringer()
+                    .object()
+                    .key(KEY_STATE).value(info.state)
+                    .key(KEY_PROGRESS).value(info.progress)
+                    .endObject();
+            value = json.toString();
+        } catch (JSONException e) {
+            Log.e(TAG, "failed to serialize app state update", e);
+        }
+        return value;
+    }
+
+    @Override
+    public HashSet<String> updateAndGetActiveSessionCache() {
+        return new HashSet<String>();
+    }
+}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
new file mode 100644
index 0000000..16ad379
--- /dev/null
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.SessionCallback;
+import android.content.pm.PackageInstaller.SessionInfo;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppState;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+public class PackageInstallerCompatVL extends PackageInstallerCompat {
+
+    private static final String TAG = "PackageInstallerCompatVL";
+    private static final boolean DEBUG = false;
+
+    private final SparseArray<SessionInfo> mPendingReplays = new SparseArray<SessionInfo>();
+    private final HashSet<String> mPendingBadgeUpdates = new HashSet<String>();
+    private final PackageInstaller mInstaller;
+    private final IconCache mCache;
+
+    private boolean mResumed;
+    private boolean mBound;
+
+    PackageInstallerCompatVL(Context context) {
+        mInstaller = context.getPackageManager().getPackageInstaller();
+        LauncherAppState.setApplicationContext(context.getApplicationContext());
+        mCache = LauncherAppState.getInstance().getIconCache();
+
+        mResumed = false;
+        mBound = false;
+
+        mInstaller.registerSessionCallback(mCallback);
+
+        // On start, send updates for all active sessions
+        for (SessionInfo info : mInstaller.getAllSessions()) {
+            mPendingReplays.append(info.getSessionId(), info);
+        }
+    }
+
+    @Override
+    public HashSet<String> updateAndGetActiveSessionCache() {
+        HashSet<String> activePackages = new HashSet<String>();
+        UserHandleCompat user = UserHandleCompat.myUserHandle();
+        for (SessionInfo info : mInstaller.getAllSessions()) {
+            addSessionInfoToCahce(info, user);
+            if (info.getAppPackageName() != null) {
+                activePackages.add(info.getAppPackageName());
+            }
+        }
+        return activePackages;
+    }
+
+    private void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
+        String packageName = info.getAppPackageName();
+        if (packageName != null) {
+            mCache.cachePackageInstallInfo(packageName, user, info.getAppIcon(),
+                    info.getAppLabel());
+        }
+    }
+
+    @Override
+    public void onStop() {
+    }
+
+    @Override
+    public void onFinishBind() {
+        mBound = true;
+        replayUpdates(null);
+    }
+
+    @Override
+    public void onPause() {
+        mResumed = false;
+    }
+
+    @Override
+    public void onResume() {
+        mResumed = true;
+        replayUpdates(null);
+    }
+
+    @Override
+    public void recordPackageUpdate(String packageName, int state, int progress) {
+        // No op
+    }
+
+    private void replayUpdates(PackageInstallInfo newInfo) {
+        if (DEBUG) Log.d(TAG, "updates resumed");
+        if (!mResumed || !mBound) {
+            // Not yet ready
+            return;
+        }
+        if ((mPendingReplays.size() == 0) && (newInfo == null) && mPendingBadgeUpdates.isEmpty()) {
+            // Nothing to update
+            return;
+        }
+
+        LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+        if (app == null) {
+            // Try again later
+            if (DEBUG) Log.d(TAG, "app is null, delaying send");
+            return;
+        }
+
+        ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
+        if ((newInfo != null) && (newInfo.state != STATUS_INSTALLED)) {
+            updates.add(newInfo);
+        }
+        for (int i = mPendingReplays.size() - 1; i >= 0; i--) {
+            SessionInfo session = mPendingReplays.valueAt(i);
+            if (session.getAppPackageName() != null) {
+                updates.add(new PackageInstallInfo(session.getAppPackageName(),
+                        STATUS_INSTALLING,
+                        (int) (session.getProgress() * 100)));
+            }
+        }
+        mPendingReplays.clear();
+        if (!updates.isEmpty()) {
+            app.setPackageState(updates);
+        }
+
+        if (!mPendingBadgeUpdates.isEmpty()) {
+            for (String pkg : mPendingBadgeUpdates) {
+                app.updatePackageBadge(pkg);
+            }
+            mPendingBadgeUpdates.clear();
+        }
+    }
+
+    private final SessionCallback mCallback = new SessionCallback() {
+
+        @Override
+        public void onCreated(int sessionId) {
+            pushSessionBadgeToLauncher(sessionId);
+        }
+
+        @Override
+        public void onFinished(int sessionId, boolean success) {
+            mPendingReplays.remove(sessionId);
+            SessionInfo session = mInstaller.getSessionInfo(sessionId);
+            if ((session != null) && (session.getAppPackageName() != null)) {
+                mPendingBadgeUpdates.remove(session.getAppPackageName());
+                // Replay all updates with a one time update for this installed package. No
+                // need to store this record for future updates, as the app list will get
+                // refreshed on resume.
+                replayUpdates(new PackageInstallInfo(session.getAppPackageName(),
+                        success ? STATUS_INSTALLED : STATUS_FAILED, 0));
+            }
+        }
+
+        @Override
+        public void onProgressChanged(int sessionId, float progress) {
+            SessionInfo session = mInstaller.getSessionInfo(sessionId);
+            if (session != null) {
+                mPendingReplays.put(sessionId, session);
+                replayUpdates(null);
+            }
+        }
+
+        @Override
+        public void onActiveChanged(int sessionId, boolean active) { }
+
+        @Override
+        public void onBadgingChanged(int sessionId) {
+            pushSessionBadgeToLauncher(sessionId);
+        }
+
+        private void pushSessionBadgeToLauncher(int sessionId) {
+            SessionInfo session = mInstaller.getSessionInfo(sessionId);
+            if (session != null) {
+                addSessionInfoToCahce(session, UserHandleCompat.myUserHandle());
+                if (session.getAppPackageName() != null) {
+                    mPendingBadgeUpdates.add(session.getAppPackageName());
+                }
+                mPendingReplays.put(sessionId, session);
+                replayUpdates(null);
+            }
+        }
+    };
+}
diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java
new file mode 100644
index 0000000..2ae6731
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserHandleCompat.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Intent;
+import android.os.Build;
+import android.os.UserHandle;
+
+import com.android.launcher3.Utilities;
+
+public class UserHandleCompat {
+    private UserHandle mUser;
+
+    private UserHandleCompat(UserHandle user) {
+        mUser = user;
+    }
+
+    private UserHandleCompat() {
+    }
+
+    public static UserHandleCompat myUserHandle() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return new UserHandleCompat(android.os.Process.myUserHandle());
+        } else {
+            return new UserHandleCompat();
+        }
+    }
+
+    static UserHandleCompat fromUser(UserHandle user) {
+        if (user == null) {
+            return null;
+        } else {
+            return new UserHandleCompat(user);
+        }
+    }
+
+    UserHandle getUser() {
+        return mUser;
+    }
+
+    @Override
+    public String toString() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return mUser.toString();
+        } else {
+            return "";
+        }
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof UserHandleCompat)) {
+            return false;
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return mUser.equals(((UserHandleCompat) other).mUser);
+        } else {
+            return true;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return mUser.hashCode();
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Adds {@link UserHandle} to the intent in for L or above.
+     * Pre-L the launcher doesn't support showing apps for multiple
+     * profiles so this is a no-op.
+     */
+    public void addToIntent(Intent intent, String name) {
+        if (Utilities.isLmpOrAbove() && mUser != null) {
+            intent.putExtra(name, mUser);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
new file mode 100644
index 0000000..1374b4e
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+
+import com.android.launcher3.Utilities;
+
+import java.util.List;
+
+public abstract class UserManagerCompat {
+    protected UserManagerCompat() {
+    }
+
+    public static UserManagerCompat getInstance(Context context) {
+        if (Utilities.isLmpOrAbove()) {
+            return new UserManagerCompatVL(context);
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return new UserManagerCompatV17(context);
+        } else {
+            return new UserManagerCompatV16();
+        }
+    }
+
+    public abstract List<UserHandleCompat> getUserProfiles();
+    public abstract long getSerialNumberForUser(UserHandleCompat user);
+    public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
+    public abstract Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user);
+    public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user);
+}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV16.java b/src/com/android/launcher3/compat/UserManagerCompatV16.java
new file mode 100644
index 0000000..32f972e
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserManagerCompatV16.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.graphics.drawable.Drawable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UserManagerCompatV16 extends UserManagerCompat {
+
+    UserManagerCompatV16() {
+    }
+
+    public List<UserHandleCompat> getUserProfiles() {
+        List<UserHandleCompat> profiles = new ArrayList<UserHandleCompat>(1);
+        profiles.add(UserHandleCompat.myUserHandle());
+        return profiles;
+    }
+
+    public UserHandleCompat getUserForSerialNumber(long serialNumber) {
+        return UserHandleCompat.myUserHandle();
+    }
+
+    public Drawable getBadgedDrawableForUser(Drawable unbadged,
+            UserHandleCompat user) {
+        return unbadged;
+    }
+
+    public long getSerialNumberForUser(UserHandleCompat user) {
+        return 0;
+    }
+
+    public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
+        return label;
+    }
+}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV17.java b/src/com/android/launcher3/compat/UserManagerCompatV17.java
new file mode 100644
index 0000000..055359a
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserManagerCompatV17.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UserManagerCompatV17 extends UserManagerCompatV16 {
+    protected UserManager mUserManager;
+
+    UserManagerCompatV17(Context context) {
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    public long getSerialNumberForUser(UserHandleCompat user) {
+        return mUserManager.getSerialNumberForUser(user.getUser());
+    }
+
+    public UserHandleCompat getUserForSerialNumber(long serialNumber) {
+        return UserHandleCompat.fromUser(mUserManager.getUserForSerialNumber(serialNumber));
+    }
+}
+
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
new file mode 100644
index 0000000..19eeabd
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -0,0 +1,65 @@
+
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class UserManagerCompatVL extends UserManagerCompatV17 {
+    private final PackageManager mPm;
+
+    UserManagerCompatVL(Context context) {
+        super(context);
+        mPm = context.getPackageManager();
+    }
+
+    @Override
+    public List<UserHandleCompat> getUserProfiles() {
+        List<UserHandle> users = mUserManager.getUserProfiles();
+        if (users == null) {
+            return Collections.EMPTY_LIST;
+        }
+        ArrayList<UserHandleCompat> compatUsers = new ArrayList<UserHandleCompat>(
+                users.size());
+        for (UserHandle user : users) {
+            compatUsers.add(UserHandleCompat.fromUser(user));
+        }
+        return compatUsers;
+    }
+
+    @Override
+    public Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user) {
+        return mPm.getUserBadgedIcon(unbadged, user.getUser());
+    }
+
+    @Override
+    public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
+        if (user == null) {
+            return label;
+        }
+        return mPm.getUserBadgedLabel(label, user.getUser());
+    }
+}
+