am ae2207a8: am 3f950065: am 2aeb1778: am f9618856: Syncing up state transition with paging transition

* commit 'ae2207a89473c3b614d345257e6524aff2a4e1e7':
diff --git a/Android.mk b/Android.mk
index 3bd20a7..110117b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,13 +26,17 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    $(call all-java-files-under, WallpaperPicker/src) \
     $(call all-renderscript-files-under, src) \
     $(call all-proto-files-under, protos)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res
+
+LOCAL_AAPT_FLAGS := --auto-add-overlay
 
 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
@@ -57,6 +61,28 @@
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
 
 LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := protoutil
+LOCAL_MODULE := launcher_protoutil_lib
+LOCAL_IS_HOST_MODULE := true
+LOCAL_JAR_MANIFEST := util/etc/manifest.txt
+LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-2.3.0-nano
 
 include $(BUILD_HOST_JAVA_LIBRARY)
+
+#
+# Protocol Buffer Debug Utility Wrapper Script
+#
+include $(CLEAR_VARS)
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := launcher_protoutil
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): launcher_protoutil_lib
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP)
+	@echo "Copy: $(PRIVATE_MODULE) ($@)"
+	$(copy-file-to-new-target)
+	$(hide) chmod 755 $@
+
+INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 901b638..591d9b6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,12 +20,9 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.launcher3">
+    <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"
@@ -46,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" />
@@ -62,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"
@@ -104,8 +110,8 @@
         </activity>
 
         <activity
-            android:name="com.android.launcher3.WallpaperPickerActivity"
-            android:theme="@style/Theme.WallpaperCropper"
+            android:name="com.android.launcher3.LauncherWallpaperPickerActivity"
+            android:theme="@style/Theme.WallpaperPicker"
             android:label="@string/pick_wallpaper"
             android:icon="@mipmap/ic_launcher_wallpaper"
             android:finishOnCloseSystemDialogs="true"
@@ -151,30 +157,35 @@
             >
         </service>
 
-        <!-- Intent received used to prepopulate the default workspace. -->
         <receiver
-            android:name="com.android.launcher3.PreloadReceiver"
-            android:permission="com.android.launcher3.permission.PRELOAD_WORKSPACE">
+            android:name="com.android.launcher3.WallpaperChangedReceiver">
             <intent-filter>
-                <action android:name="com.android.launcher3.action.PRELOAD_WORKSPACE" />
+                <action android:name="android.intent.action.WALLPAPER_CHANGED" />
             </intent-filter>
         </receiver>
 
         <!-- 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>
 
@@ -196,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/CleanSpec.mk b/CleanSpec.mk
index c132395..b2c5266 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,6 +50,8 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/WallpaperPicker/AndroidManifest.xml b/WallpaperPicker/AndroidManifest.xml
new file mode 100644
index 0000000..86a94d0
--- /dev/null
+++ b/WallpaperPicker/AndroidManifest.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.launcher3"
+        android:versionCode="1"
+        android:versionName="1.0"
+        >
+
+    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
+
+</manifest>
diff --git a/WallpaperPicker/README b/WallpaperPicker/README
new file mode 100644
index 0000000..d8efb07
--- /dev/null
+++ b/WallpaperPicker/README
@@ -0,0 +1,4 @@
+This project contains the wallpaper picker for Launcher3. It's in a separate
+folder to organize the code separately from the rest of the launcher, and has
+a manifest so that a separate Eclipse project can exist for the wallpaper
+picker (necessary to have the Eclipse build work)
\ No newline at end of file
diff --git a/res/drawable-hdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png
similarity index 100%
rename from res/drawable-hdpi/ic_actionbar_accept.png
rename to WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_images.png b/WallpaperPicker/res/drawable-hdpi/ic_images.png
similarity index 100%
rename from res/drawable-hdpi/ic_images.png
rename to WallpaperPicker/res/drawable-hdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png
similarity index 100%
rename from res/drawable-hdpi/tile_picker_focused.9.png
rename to WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png
similarity index 100%
rename from res/drawable-hdpi/tile_picker_pressed.9.png
rename to WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png
similarity index 100%
rename from res/drawable-hdpi/tile_picker_selected.9.png
rename to WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png
similarity index 100%
rename from res/drawable-hdpi/tile_shadow_bottom.9.png
rename to WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png
similarity index 100%
rename from res/drawable-hdpi/tile_shadow_top.9.png
rename to WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png
similarity index 100%
rename from res/drawable-mdpi/ic_actionbar_accept.png
rename to WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_images.png b/WallpaperPicker/res/drawable-mdpi/ic_images.png
similarity index 100%
rename from res/drawable-mdpi/ic_images.png
rename to WallpaperPicker/res/drawable-mdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png
similarity index 100%
rename from res/drawable-mdpi/tile_picker_focused.9.png
rename to WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png
similarity index 100%
rename from res/drawable-mdpi/tile_picker_pressed.9.png
rename to WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png
similarity index 100%
rename from res/drawable-mdpi/tile_picker_selected.9.png
rename to WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png
similarity index 100%
rename from res/drawable-mdpi/tile_shadow_bottom.9.png
rename to WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png
similarity index 100%
rename from res/drawable-mdpi/tile_shadow_top.9.png
rename to WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png
similarity index 100%
rename from res/drawable-xhdpi/ic_actionbar_accept.png
rename to WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_images.png b/WallpaperPicker/res/drawable-xhdpi/ic_images.png
similarity index 100%
rename from res/drawable-xhdpi/ic_images.png
rename to WallpaperPicker/res/drawable-xhdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png
similarity index 100%
rename from res/drawable-xhdpi/tile_picker_focused.9.png
rename to WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png
similarity index 100%
rename from res/drawable-xhdpi/tile_picker_pressed.9.png
rename to WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png
similarity index 100%
rename from res/drawable-xhdpi/tile_picker_selected.9.png
rename to WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png
similarity index 100%
rename from res/drawable-xhdpi/tile_shadow_bottom.9.png
rename to WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png
similarity index 100%
rename from res/drawable-xhdpi/tile_shadow_top.9.png
rename to WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png
Binary files differ
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/res/drawable-xxhdpi/ic_images.png b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
similarity index 100%
rename from res/drawable-xxhdpi/ic_images.png
rename to WallpaperPicker/res/drawable-xxhdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png
similarity index 100%
rename from res/drawable-xxhdpi/tile_picker_focused.9.png
rename to WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png
similarity index 100%
rename from res/drawable-xxhdpi/tile_picker_pressed.9.png
rename to WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png
similarity index 100%
rename from res/drawable-xxhdpi/tile_picker_selected.9.png
rename to WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png
similarity index 100%
rename from res/drawable-xxhdpi/tile_shadow_bottom.9.png
rename to WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png
similarity index 100%
rename from res/drawable-xxhdpi/tile_shadow_top.9.png
rename to WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable/wallpaper_tile_fg.xml b/WallpaperPicker/res/drawable/wallpaper_tile_fg.xml
similarity index 100%
rename from res/drawable/wallpaper_tile_fg.xml
rename to WallpaperPicker/res/drawable/wallpaper_tile_fg.xml
diff --git a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
new file mode 100644
index 0000000..8e349b7
--- /dev/null
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.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"
+    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/res/layout/wallpaper_cropper.xml b/WallpaperPicker/res/layout/wallpaper_cropper.xml
similarity index 100%
rename from res/layout/wallpaper_cropper.xml
rename to WallpaperPicker/res/layout/wallpaper_cropper.xml
diff --git a/res/layout/wallpaper_picker.xml b/WallpaperPicker/res/layout/wallpaper_picker.xml
similarity index 100%
rename from res/layout/wallpaper_picker.xml
rename to WallpaperPicker/res/layout/wallpaper_picker.xml
diff --git a/res/layout/wallpaper_picker_image_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
similarity index 100%
rename from res/layout/wallpaper_picker_image_picker_item.xml
rename to WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
diff --git a/res/layout/wallpaper_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_item.xml
similarity index 100%
rename from res/layout/wallpaper_picker_item.xml
rename to WallpaperPicker/res/layout/wallpaper_picker_item.xml
diff --git a/res/layout/wallpaper_picker_live_wallpaper_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
similarity index 100%
rename from res/layout/wallpaper_picker_live_wallpaper_item.xml
rename to WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
diff --git a/res/layout/wallpaper_picker_third_party_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
similarity index 100%
rename from res/layout/wallpaper_picker_third_party_item.xml
rename to WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
diff --git a/res/menu/cab_delete_wallpapers.xml b/WallpaperPicker/res/menu/cab_delete_wallpapers.xml
similarity index 100%
rename from res/menu/cab_delete_wallpapers.xml
rename to WallpaperPicker/res/menu/cab_delete_wallpapers.xml
diff --git a/res/mipmap-hdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png
similarity index 100%
rename from res/mipmap-hdpi/ic_launcher_wallpaper.png
rename to WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png
similarity index 100%
rename from res/mipmap-mdpi/ic_launcher_wallpaper.png
rename to WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png
similarity index 100%
rename from res/mipmap-xhdpi/ic_launcher_wallpaper.png
rename to WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png
similarity index 100%
rename from res/mipmap-xxhdpi/ic_launcher_wallpaper.png
rename to WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png
Binary files differ
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/res/values-nodpi/wallpapers.xml b/WallpaperPicker/res/values-nodpi/wallpapers.xml
similarity index 100%
rename from res/values-nodpi/wallpapers.xml
rename to WallpaperPicker/res/values-nodpi/wallpapers.xml
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/res/values-sw340dp-land/dimens.xml b/WallpaperPicker/res/values-sw600dp/config.xml
similarity index 83%
rename from res/values-sw340dp-land/dimens.xml
rename to WallpaperPicker/res/values-sw600dp/config.xml
index 7901dc4..62342dc 100644
--- a/res/values-sw340dp-land/dimens.xml
+++ b/WallpaperPicker/res/values-sw600dp/config.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 201 The Android Open Source Project
+<!-- 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.
@@ -13,8 +13,6 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">50dp</dimen>
+    <bool name="allow_rotation">true</bool>
 </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/res/values-sw340dp-port/dimens.xml b/WallpaperPicker/res/values-sw720dp/dimens.xml
similarity index 60%
copy from res/values-sw340dp-port/dimens.xml
copy to WallpaperPicker/res/values-sw720dp/dimens.xml
index e360565..9ae155b 100644
--- a/res/values-sw340dp-port/dimens.xml
+++ b/WallpaperPicker/res/values-sw720dp/dimens.xml
@@ -15,6 +15,14 @@
 -->
 
 <resources>
-<!-- Clings -->
-    <dimen name="folderClingMarginTop">70dp</dimen>
+    <dimen name="app_icon_size">72dp</dimen>
+
+<!-- QSB -->
+    <dimen name="toolbar_button_vertical_padding">8dip</dimen>
+    <dimen name="toolbar_button_horizontal_padding">8dip</dimen>
+
+    <!-- When dragging items on the workspace, the number of dps by which the position of
+     the drag view should be offset from the position of the original view. -->
+    <dimen name="dragViewOffsetX">0dp</dimen>
+    <dimen name="dragViewOffsetY">0dp</dimen>
 </resources>
diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml
new file mode 100644
index 0000000..b489090
--- /dev/null
+++ b/WallpaperPicker/res/values-sw720dp/styles.xml
@@ -0,0 +1,24 @@
+<?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>
+    </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/colors.xml b/WallpaperPicker/res/values/colors.xml
new file mode 100644
index 0000000..adae7cf
--- /dev/null
+++ b/WallpaperPicker/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 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>
+    <color name="wallpaper_picker_translucent_gray">#66000000</color>
+</resources>
diff --git a/res/drawable/cling_arrow_end.xml b/WallpaperPicker/res/values/config.xml
similarity index 74%
rename from res/drawable/cling_arrow_end.xml
rename to WallpaperPicker/res/values/config.xml
index 3f63c7d..71580b5 100644
--- a/res/drawable/cling_arrow_end.xml
+++ b/WallpaperPicker/res/values/config.xml
@@ -13,7 +13,9 @@
      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>
+<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/res/drawable/cling_arrow_end.xml b/WallpaperPicker/res/values/dimens.xml
similarity index 74%
copy from res/drawable/cling_arrow_end.xml
copy to WallpaperPicker/res/values/dimens.xml
index 3f63c7d..0447c6d 100644
--- a/res/drawable/cling_arrow_end.xml
+++ b/WallpaperPicker/res/values/dimens.xml
@@ -4,16 +4,19 @@
      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>
+
+<resources>
+<!-- Wallpaper picker -->
+    <dimen name="wallpaperThumbnailWidth">106.5dp</dimen>
+    <dimen name="wallpaperThumbnailHeight">94.5dp</dimen>
+    <dimen name="wallpaperItemIconSize">32dp</dimen>
+</resources>
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
new file mode 100644
index 0000000..1ee3513
--- /dev/null
+++ b/WallpaperPicker/res/values/strings.xml
@@ -0,0 +1,53 @@
+<?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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
+    <string name="wallpaper_instructions">Set wallpaper</string>
+    <!-- Error message when an image is selected as a wallpaper,
+         but the wallpaper picker cannot load it -->
+    <string name="image_load_fail">Coudn\'t load image</string>
+    <!-- Error message when an image is selected as a wallpaper,
+         but the wallpaper cropper cannot load it. The user will
+         usually see this when using another app and trying to set
+         an image as the wallpaper -->
+    <string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
+    <!-- Shown when wallpapers are selected in Wallpaper picker -->
+    <!-- String indicating how many media item(s) is(are) selected
+            eg. 1 selected [CHAR LIMIT=30] -->
+    <plurals name="number_of_items_selected">
+        <item quantity="zero">%1$d selected</item>
+        <item quantity="one">%1$d selected</item>
+        <item quantity="other">%1$d selected</item>
+    </plurals>
+    <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list.
+         e.g. "Wallpaper 3 of 10" -->
+    <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string>
+    <!-- Accessibility string used to announce that a wallpaper has been selected. -->
+    <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string>
+
+    <!-- Label on button to delete wallpaper(s) -->
+    <string name="wallpaper_delete">Delete</string>
+    <!-- Label on button in Wallpaper Picker to pick an image -->
+    <string name="pick_image">Pick image</string>
+    <!-- Option in "Select wallpaper from" dialog box -->
+    <string name="pick_wallpaper">Wallpapers</string>
+    <!-- Title of activity for cropping wallpapers -->
+    <string name="crop_wallpaper">Crop wallpaper</string>
+</resources>
diff --git a/WallpaperPicker/res/values/styles.xml b/WallpaperPicker/res/values/styles.xml
new file mode 100644
index 0000000..16b11f2
--- /dev/null
+++ b/WallpaperPicker/res/values/styles.xml
@@ -0,0 +1,44 @@
+<?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>
+    </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">
+        <item name="android:displayOptions">showCustom</item>
+        <item name="android:background">#88000000</item>
+    </style>
+
+    <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+    </style>
+
+    <style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.Holo.ActionButton">
+        <item name="android:textColor">#ffffffff</item>
+    </style>
+</resources>
diff --git a/src/android/util/Pools.java b/WallpaperPicker/src/android/util/Pools.java
similarity index 100%
rename from src/android/util/Pools.java
rename to WallpaperPicker/src/android/util/Pools.java
diff --git a/src/com/android/gallery3d/common/BitmapUtils.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
similarity index 100%
rename from src/com/android/gallery3d/common/BitmapUtils.java
rename to WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
diff --git a/src/com/android/gallery3d/common/Utils.java b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
similarity index 100%
rename from src/com/android/gallery3d/common/Utils.java
rename to WallpaperPicker/src/com/android/gallery3d/common/Utils.java
diff --git a/src/com/android/gallery3d/exif/ByteBufferInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ByteBufferInputStream.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java
diff --git a/src/com/android/gallery3d/exif/CountedDataInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java
similarity index 100%
rename from src/com/android/gallery3d/exif/CountedDataInputStream.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java
diff --git a/src/com/android/gallery3d/exif/ExifData.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifData.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java
diff --git a/src/com/android/gallery3d/exif/ExifInterface.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifInterface.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
diff --git a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifInvalidFormatException.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java
diff --git a/src/com/android/gallery3d/exif/ExifModifier.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java
similarity index 99%
rename from src/com/android/gallery3d/exif/ExifModifier.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java
index f00362b..0531cba 100644
--- a/src/com/android/gallery3d/exif/ExifModifier.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java
@@ -18,7 +18,6 @@
 
 import android.util.Log;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
diff --git a/src/com/android/gallery3d/exif/ExifOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifOutputStream.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java
diff --git a/src/com/android/gallery3d/exif/ExifParser.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifParser.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java
diff --git a/src/com/android/gallery3d/exif/ExifReader.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifReader.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java
diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java
similarity index 100%
rename from src/com/android/gallery3d/exif/ExifTag.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java
diff --git a/src/com/android/gallery3d/exif/IfdData.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java
similarity index 100%
rename from src/com/android/gallery3d/exif/IfdData.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java
diff --git a/src/com/android/gallery3d/exif/IfdId.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java
similarity index 100%
rename from src/com/android/gallery3d/exif/IfdId.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java
diff --git a/src/com/android/gallery3d/exif/JpegHeader.java b/WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java
similarity index 100%
rename from src/com/android/gallery3d/exif/JpegHeader.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java
diff --git a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java
similarity index 100%
rename from src/com/android/gallery3d/exif/OrderedDataOutputStream.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java
diff --git a/src/com/android/gallery3d/exif/Rational.java b/WallpaperPicker/src/com/android/gallery3d/exif/Rational.java
similarity index 100%
rename from src/com/android/gallery3d/exif/Rational.java
rename to WallpaperPicker/src/com/android/gallery3d/exif/Rational.java
diff --git a/src/com/android/gallery3d/glrenderer/BasicTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/BasicTexture.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/BitmapTexture.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/GLCanvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java
similarity index 99%
rename from src/com/android/gallery3d/glrenderer/GLCanvas.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java
index 305e905..5b07477 100644
--- a/src/com/android/gallery3d/glrenderer/GLCanvas.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java
@@ -20,8 +20,6 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 
-import javax.microedition.khronos.opengles.GL11;
-
 //
 // GLCanvas gives a convenient interface to draw using OpenGL.
 //
diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/GLES20Canvas.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
diff --git a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
diff --git a/src/com/android/gallery3d/glrenderer/GLId.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/GLId.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java
diff --git a/src/com/android/gallery3d/glrenderer/GLPaint.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/GLPaint.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
diff --git a/src/com/android/gallery3d/glrenderer/RawTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/RawTexture.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/Texture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/Texture.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java
diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
similarity index 100%
rename from src/com/android/gallery3d/glrenderer/UploadedTexture.java
rename to WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
diff --git a/src/com/android/gallery3d/util/IntArray.java b/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java
similarity index 100%
rename from src/com/android/gallery3d/util/IntArray.java
rename to WallpaperPicker/src/com/android/gallery3d/util/IntArray.java
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/src/com/android/launcher3/CheckableFrameLayout.java b/WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java
similarity index 100%
rename from src/com/android/launcher3/CheckableFrameLayout.java
rename to WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java
diff --git a/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java
similarity index 100%
rename from src/com/android/launcher3/CropView.java
rename to WallpaperPicker/src/com/android/launcher3/CropView.java
diff --git a/src/com/android/launcher3/DrawableTileSource.java b/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java
similarity index 100%
rename from src/com/android/launcher3/DrawableTileSource.java
rename to WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java
diff --git a/src/com/android/launcher3/LiveWallpaperListAdapter.java b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
similarity index 97%
rename from src/com/android/launcher3/LiveWallpaperListAdapter.java
rename to WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
index 152a75d..88f4461 100644
--- a/src/com/android/launcher3/LiveWallpaperListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
@@ -122,9 +122,8 @@
             Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
             preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
                     mInfo.getComponent());
-            a.onLiveWallpaperPickerLaunch();
-            Utilities.startActivityForResultSafely(
-                    a, preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
+            a.onLiveWallpaperPickerLaunch(mInfo);
+            a.startActivityForResultSafely(preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
         }
     }
 
diff --git a/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
similarity index 81%
rename from src/com/android/launcher3/SavedWallpaperImages.java
rename to WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index 58add70..2bdf8f1 100644
--- a/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/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
similarity index 97%
rename from src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
rename to WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
index 494694c..7a4d48c 100644
--- a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
@@ -56,8 +56,8 @@
                     mResolveInfo.activityInfo.packageName, mResolveInfo.activityInfo.name);
             Intent launchIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
             launchIntent.setComponent(itemComponentName);
-            Utilities.startActivityForResultSafely(
-                    a, launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
+            a.startActivityForResultSafely(
+                    launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
         }
     }
 
diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
similarity index 87%
rename from src/com/android/launcher3/WallpaperCropActivity.java
rename to WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 65223ad..d5c7cd9 100644
--- a/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -71,8 +71,11 @@
     public static final int MAX_BMAP_IN_INTENT = 750000;
     private static final float WALLPAPER_SCREENS_SPAN = 2f;
 
+    protected static Point sDefaultWallpaperSize;
+
     protected CropView mCropView;
     protected Uri mUri;
+    protected View mSetWallpaperButton;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -109,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) {
@@ -120,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) {
@@ -134,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;
             }
@@ -204,32 +233,34 @@
     }
 
     static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
-        Point minDims = new Point();
-        Point maxDims = new Point();
-        windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+        if (sDefaultWallpaperSize == null) {
+            Point minDims = new Point();
+            Point maxDims = new Point();
+            windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
 
-        int maxDim = Math.max(maxDims.x, maxDims.y);
-        int minDim = Math.max(minDims.x, minDims.y);
+            int maxDim = Math.max(maxDims.x, maxDims.y);
+            int minDim = Math.max(minDims.x, minDims.y);
 
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            Point realSize = new Point();
-            windowManager.getDefaultDisplay().getRealSize(realSize);
-            maxDim = Math.max(realSize.x, realSize.y);
-            minDim = Math.min(realSize.x, realSize.y);
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                Point realSize = new Point();
+                windowManager.getDefaultDisplay().getRealSize(realSize);
+                maxDim = Math.max(realSize.x, realSize.y);
+                minDim = Math.min(realSize.x, realSize.y);
+            }
+
+            // We need to ensure that there is enough extra space in the wallpaper
+            // for the intended parallax effects
+            final int defaultWidth, defaultHeight;
+            if (isScreenLarge(res)) {
+                defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
+                defaultHeight = maxDim;
+            } else {
+                defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
+                defaultHeight = maxDim;
+            }
+            sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
         }
-
-        // We need to ensure that there is enough extra space in the wallpaper
-        // for the intended
-        // parallax effects
-        final int defaultWidth, defaultHeight;
-        if (isScreenLarge(res)) {
-            defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
-            defaultHeight = maxDim;
-        } else {
-            defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
-            defaultHeight = maxDim;
-        }
-        return new Point(defaultWidth, defaultHeight);
+        return sDefaultWallpaperSize;
     }
 
     public static int getRotationFromExif(String path) {
@@ -267,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);
@@ -274,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() {
@@ -326,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();
@@ -340,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 };
@@ -351,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
@@ -777,23 +832,32 @@
         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
 
-        new Thread("suggestWallpaperDimension") {
-            public void run() {
-                // 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);
-                wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
+        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;
             }
-        }.start();
+        }
+
+        if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
+                savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
+            wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
+        }
     }
 
     protected static RectF getMaxCropRect(
diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
similarity index 74%
rename from src/com/android/launcher3/WallpaperPickerActivity.java
rename to WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 2da05c9..0728537 100644
--- a/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;
@@ -57,16 +56,18 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
+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;
@@ -84,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;
@@ -102,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;
         }
@@ -125,7 +132,7 @@
         public void onClick(WallpaperPickerActivity a) {
             Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
             intent.setType("image/*");
-            Utilities.startActivityForResultSafely(a, intent, IMAGE_PICK);
+            a.startActivityForResultSafely(intent, IMAGE_PICK);
         }
     }
 
@@ -143,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) {
@@ -189,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;
@@ -215,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) {
@@ -231,8 +266,8 @@
         }
     }
 
+    @TargetApi(Build.VERSION_CODES.KITKAT)
     public static class DefaultWallpaperInfo extends WallpaperTileInfo {
-        public Drawable mThumb;
         public DefaultWallpaperInfo(Drawable thumb) {
             mThumb = thumb;
         }
@@ -243,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);
             }
@@ -271,14 +314,73 @@
         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() {
-            LauncherViewPropertyAnimator mAnim;
+            ViewPropertyAnimator mAnim;
             @Override
             public void onTouchDown() {
                 if (mAnim != null) {
@@ -287,17 +389,14 @@
                 if (mWallpaperStrip.getAlpha() == 1f) {
                     mIgnoreNextTap = true;
                 }
-                mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
+                mAnim = mWallpaperStrip.animate();
                 mAnim.alpha(0f)
-                     .setDuration(150)
-                     .addListener(new Animator.AnimatorListener() {
-                         public void onAnimationStart(Animator animator) { }
-                         public void onAnimationEnd(Animator animator) {
-                             mWallpaperStrip.setVisibility(View.INVISIBLE);
-                         }
-                         public void onAnimationCancel(Animator animator) { }
-                         public void onAnimationRepeat(Animator animator) { }
-                     });
+                    .setDuration(150)
+                    .withEndAction(new Runnable() {
+                        public void run() {
+                            mWallpaperStrip.setVisibility(View.INVISIBLE);
+                        }
+                    });
                 mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
                 mAnim.start();
             }
@@ -314,7 +413,7 @@
                         mAnim.cancel();
                     }
                     mWallpaperStrip.setVisibility(View.VISIBLE);
-                    mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
+                    mAnim = mWallpaperStrip.animate();
                     mAnim.alpha(1f)
                          .setDuration(150)
                          .setInterpolator(new DecelerateInterpolator(0.75f));
@@ -332,6 +431,7 @@
                     }
                     return;
                 }
+                mSetWallpaperButton.setEnabled(true);
                 WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
                 if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
                     selectTile(v);
@@ -360,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
@@ -413,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() {
@@ -432,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);
                 }
@@ -463,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() {
@@ -512,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);
@@ -519,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;
@@ -540,7 +644,9 @@
                     CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
                     c.setChecked(false);
                 }
-                mSelectedTile.setSelected(true);
+                if (mSelectedTile != null) {
+                    mSelectedTile.setSelected(true);
+                }
                 mActionMode = null;
             }
         };
@@ -553,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(
@@ -576,23 +683,22 @@
         }
     }
 
-    public boolean enableRotation() {
-        return super.enableRotation() || Launcher.sForceEnableRotation;
-    }
-
     protected Bitmap getThumbnailOfLastPhoto() {
         Cursor cursor = MediaStore.Images.Media.query(getContentResolver(),
                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                 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;
     }
 
@@ -607,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,
@@ -717,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().
@@ -732,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);
                 }
@@ -753,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);
@@ -768,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();
@@ -789,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) {
@@ -827,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()) {
@@ -844,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) {
@@ -853,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(
@@ -878,7 +1061,7 @@
                 c.setBitmap(null);
             }
             if (thumb != null) {
-                defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb);
+                defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
             }
         }
         if (defaultWallpaperExists) {
@@ -901,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);
@@ -914,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() {
@@ -932,7 +1112,8 @@
         return mSavedImages;
     }
 
-    public void onLiveWallpaperPickerLaunch() {
+    public void onLiveWallpaperPickerLaunch(WallpaperInfo info) {
+        mLastClickedLiveWallpaperInfo = info;
         mLiveWallpaperInfoOnPickerLaunch = WallpaperManager.getInstance(this).getWallpaperInfo();
     }
 
@@ -950,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;
 
@@ -1001,4 +1169,10 @@
 
         return view;
     }
+
+    // In Launcher3, we override this with a method that catches exceptions
+    // from starting activities; didn't want to copy and paste code into here
+    public void startActivityForResultSafely(Intent intent, int requestCode) {
+        startActivityForResult(intent, requestCode);
+    }
 }
diff --git a/src/com/android/launcher3/WallpaperRootView.java b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
similarity index 100%
rename from src/com/android/launcher3/WallpaperRootView.java
rename to WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
similarity index 97%
rename from src/com/android/photos/BitmapRegionTileSource.java
rename to WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 8511de2..66ece4f 100644
--- a/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -24,9 +24,7 @@
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.Paint;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -247,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;
@@ -282,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
@@ -313,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/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
similarity index 100%
rename from src/com/android/photos/views/BlockingGLTextureView.java
rename to WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
similarity index 100%
rename from src/com/android/photos/views/TiledImageRenderer.java
rename to WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
diff --git a/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
similarity index 96%
rename from src/com/android/photos/views/TiledImageView.java
rename to WallpaperPicker/src/com/android/photos/views/TiledImageView.java
index af4199c..94063b0 100644
--- a/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 9b59b21..0b28c0e 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -8,6 +8,9 @@
   public void onClickAllAppsButton(android.view.View);
   public void onClickAppMarketButton(android.view.View);
   public void dismissFirstRunCling(android.view.View);
+  public void dismissMigrationClingCopyApps(android.view.View);
+  public void dismissMigrationClingUseDefault(android.view.View);
+  public void dismissMigrationWorkspaceCling(android.view.View);
   public void dismissWorkspaceCling(android.view.View);
   public void dismissAllAppsCling(android.view.View);
 }
@@ -49,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/on_boarding_welcome.png b/res/drawable-hdpi/on_boarding_welcome.png
new file mode 100644
index 0000000..852a0cb
--- /dev/null
+++ b/res/drawable-hdpi/on_boarding_welcome.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/on_boarding_welcome.png b/res/drawable-mdpi/on_boarding_welcome.png
new file mode 100644
index 0000000..1d12e83
--- /dev/null
+++ b/res/drawable-mdpi/on_boarding_welcome.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-sw720dp-hdpi/workspace_bg.9.png b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
new file mode 100644
index 0000000..5bbfa4f
--- /dev/null
+++ b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-mdpi/workspace_bg.9.png b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
new file mode 100644
index 0000000..2856e09
--- /dev/null
+++ b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-xhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
new file mode 100644
index 0000000..72269f2
--- /dev/null
+++ b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
new file mode 100644
index 0000000..efc9b04
--- /dev/null
+++ b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.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/on_boarding_welcome.png b/res/drawable-xhdpi/on_boarding_welcome.png
new file mode 100644
index 0000000..8c101e0
--- /dev/null
+++ b/res/drawable-xhdpi/on_boarding_welcome.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_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
new file mode 100644
index 0000000..307cba8
--- /dev/null
+++ b/res/layout-land/migration_cling.xml
@@ -0,0 +1,103 @@
+<?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.
+-->
+<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"
+    android:background="#FF009688"
+    android:baselineAligned="false"
+    android:gravity="center_vertical" >
+
+    <FrameLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" >
+
+        <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="@dimen/cling_migration_logo_width"
+            android:layout_height="@dimen/cling_migration_logo_height"
+            android:layout_gravity="center"
+            android:src="@drawable/ic_migration" />
+    </FrameLayout>
+
+    <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/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 2b3cf81..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,32 +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/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
new file mode 100644
index 0000000..dde8dbc
--- /dev/null
+++ b/res/layout-port/migration_cling.xml
@@ -0,0 +1,106 @@
+<?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.
+-->
+<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"
+    android:background="#FF009688" >
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        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="@dimen/cling_migration_content_width"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/ic_cling_migration"
+            android:layout_marginStart="@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>
+    </RelativeLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout-port/search_bar.xml b/res/layout-port/qsb.xml
similarity index 96%
rename from res/layout-port/search_bar.xml
rename to res/layout-port/qsb.xml
index 1c96ca3..4c9963d 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-port/qsb.xml
@@ -16,13 +16,12 @@
 <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">
    <!-- Global search icon -->
    <com.android.launcher3.HolographicLinearLayout
-        style="@style/SearchButton"
+        style="@style/SearchButton.WithPaddingStart"
         launcher:sourceImageViewId="@+id/search_button"
         android:id="@+id/search_button_container"
         android:layout_width="match_parent"
@@ -31,7 +30,6 @@
         android:layout_centerVertical="true"
         android:layout_alignParentStart="true"
         android:layout_toStartOf="@+id/voice_button_container"
-        android:paddingStart="8dp"
         android:onClick="onClickSearchButton"
         android:focusable="true"
         android:clickable="true"
@@ -57,6 +55,7 @@
         android:layout_centerVertical="true"
         android:layout_alignParentEnd="true"
         android:paddingEnd="8dp"
+        android:paddingRight="8dp"
         android:onClick="onClickVoiceButton"
         android:focusable="true"
         android:clickable="true"
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-sw720dp/market_button.xml b/res/layout-sw720dp/market_button.xml
index f1e9959..7eaeafa 100644
--- a/res/layout-sw720dp/market_button.xml
+++ b/res/layout-sw720dp/market_button.xml
@@ -18,8 +18,8 @@
     style="@style/MarketButton"
     android:onClick="onClickAppMarketButton"
     android:gravity="center"
-    android:paddingStart="32dp"
-    android:paddingEnd="32dp"
+    android:paddingLeft="32dp"
+    android:paddingRight="32dp"
     android:drawablePadding="10dp"
     android:background="@drawable/tab_widget_indicator_selector"
     android:text="@string/market"
diff --git a/res/layout-port/search_bar.xml b/res/layout-sw720dp/qsb.xml
similarity index 95%
copy from res/layout-port/search_bar.xml
copy to res/layout-sw720dp/qsb.xml
index 1c96ca3..4c9963d 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-sw720dp/qsb.xml
@@ -16,13 +16,12 @@
 <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">
    <!-- Global search icon -->
    <com.android.launcher3.HolographicLinearLayout
-        style="@style/SearchButton"
+        style="@style/SearchButton.WithPaddingStart"
         launcher:sourceImageViewId="@+id/search_button"
         android:id="@+id/search_button_container"
         android:layout_width="match_parent"
@@ -31,7 +30,6 @@
         android:layout_centerVertical="true"
         android:layout_alignParentStart="true"
         android:layout_toStartOf="@+id/voice_button_container"
-        android:paddingStart="8dp"
         android:onClick="onClickSearchButton"
         android:focusable="true"
         android:clickable="true"
@@ -57,6 +55,7 @@
         android:layout_centerVertical="true"
         android:layout_alignParentEnd="true"
         android:paddingEnd="8dp"
+        android:paddingRight="8dp"
         android:onClick="onClickVoiceButton"
         android:focusable="true"
         android:clickable="true"
diff --git a/res/layout-sw720dp/search_bar.xml b/res/layout-sw720dp/search_bar.xml
deleted file mode 100644
index 69dd61a..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"
-        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:paddingStart="8dp"
-        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: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/actionbar_set_wallpaper.xml b/res/layout/actionbar_set_wallpaper.xml
deleted file mode 100644
index 1622742..0000000
--- a/res/layout/actionbar_set_wallpaper.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="?android:actionButtonStyle"
-    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>
diff --git a/res/layout/add_list_item.xml b/res/layout/add_list_item.xml
index 0ae0113..e937d7b 100644
--- a/res/layout/add_list_item.xml
+++ b/res/layout/add_list_item.xml
@@ -21,5 +21,5 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:gravity="center_vertical"
     android:drawablePadding="14dip"
-    android:paddingStart="15dip"
-    android:paddingEnd="15dip" />
+    android:paddingLeft="15dip"
+    android:paddingRight="15dip" />
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 f2d2342..e299b32 100644
--- a/res/layout/apps_customize_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -25,23 +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"
+    <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:paddingStart="@dimen/app_widget_preview_padding_left"
-        android:paddingEnd="@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"
@@ -55,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"
@@ -72,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/layout/appwidget_error.xml b/res/layout/appwidget_error.xml
index f5a9148..03d4ae4 100644
--- a/res/layout/appwidget_error.xml
+++ b/res/layout/appwidget_error.xml
@@ -19,8 +19,8 @@
     android:layout_height="wrap_content"
     android:paddingTop="10dip"
     android:paddingBottom="10dip"
-    android:paddingStart="20dip"
-    android:paddingEnd="20dip"
+    android:paddingLeft="20dip"
+    android:paddingRight="20dip"
     android:gravity="center"
     android:background="@drawable/bg_appwidget_error"
     android:textAppearance="?android:attr/textAppearanceMediumInverse"
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/market_button.xml b/res/layout/market_button.xml
index 4a718c3..41e6ec7 100644
--- a/res/layout/market_button.xml
+++ b/res/layout/market_button.xml
@@ -18,8 +18,8 @@
     style="@style/MarketButton"
     android:onClick="onClickAppMarketButton"
     android:gravity="center"
-    android:paddingStart="16dp"
-    android:paddingEnd="16dp"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
     android:background="@drawable/tab_widget_indicator_selector"
     android:contentDescription="@string/market"
     android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
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/mipmap-xxhdpi/on_boarding_welcome.png b/res/mipmap-xxhdpi/on_boarding_welcome.png
new file mode 100644
index 0000000..7b11dea
--- /dev/null
+++ b/res/mipmap-xxhdpi/on_boarding_welcome.png
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index e167189..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Tuisskerm %1$d van %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Programme-bladsy %1$d van %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Legstukke-bladsy %1$d van %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Welkom!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Maak jouself tuis."</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">"Skep meer skerms vir programme en vouers"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopieer jou program-ikone"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Voer ikone en vouers vanaf jou ou tuisskerms in?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIEER IKONE"</string>
+    <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>
@@ -114,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 6e8aaa4..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"እንኳን ደህና መጡ!"</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="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>
@@ -114,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 73ee690..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,23 +77,29 @@
     <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>
-    <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="7257389003637362144">"مرحبًا!"</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="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>
@@ -114,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 2f53fa3..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Добре дошли!"</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="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>
@@ -114,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 3400482..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla d\'inici %1$d de %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pàgina d\'aplicacions %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="7257389003637362144">"Hola!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Us donem la benvinguda"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Personalitza la pantalla d\'inici"</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 pantalles per a aplicacions i carpetes"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copiar les icones d\'aplicació"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importar icones i carpetes de pantalles d\'inici anteriors?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIA LES ICONES."</string>
+    <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>
@@ -114,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 1061e79..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>
@@ -96,15 +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 aplikací %1$d z %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stránka widgetů %1$d z %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Vítejte!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Vítejte"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Udělejte si pohodlí."</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">"Vytvořte několik obrazovek pro aplikace a složky"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Zkopírování ikon aplikací"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Chcete importovat ikony a složky ze svých starých ploch?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"ZKOPÍROVAT IKONY"</string>
+    <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>
@@ -114,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 5db246e..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Startskærm %1$d ud af %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-side %1$d ud af %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets-side %1$d ud af %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Velkommen"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Føl dig hjemme."</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">"Opret flere skærme til apps og mapper"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiér dine appikoner"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Vil du importere ikoner og mapper fra gamle startskærme?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIÉR IKONER"</string>
+    <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>
@@ -114,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 7a5e7e6..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,15 +86,20 @@
     <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="7257389003637362144">"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>
-    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Weitere Bildschirme für Apps und Ordner erstellen"</string>
+    <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Mehr Bildschirme für Apps und Ordner erstellen"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"App-Symbole kopieren"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Symbole und Ordner alter Startbildschirme importieren?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"Symbole kopieren"</string>
+    <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>
@@ -114,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 74322e0..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Καλώς ορίσατε!"</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="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>
@@ -114,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 316585e..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps page %1$d of %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets page %1$d of %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Welcome!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Make yourself at home."</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">"Create more screens for apps and folders"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copy your app icons"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Import icons and folders from your old Home screens?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
+    <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>
@@ -114,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 316585e..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps page %1$d of %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets page %1$d of %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Welcome!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Make yourself at home."</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">"Create more screens for apps and folders"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copy your app icons"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Import icons and folders from your old Home screens?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
+    <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>
@@ -114,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 c9a44a9..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,15 +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="7257389003637362144">"¡Bienvenido/a!"</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 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>
@@ -114,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 193e096..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>
@@ -96,15 +86,20 @@
     <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á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="7257389003637362144">"Te damos la bienvenida"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Te damos la bienvenida"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Personaliza tu pantalla de inicio."</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 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">"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>
@@ -114,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 f026b08..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Avaekraan %1$d/%2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Rakenduste leht %1$d/%2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Vidinate leht %1$d/%2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Tere tulemast!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Tere tulemast"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Tundke end nagu kodus."</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">"Looge rakenduste ja kaustade jaoks rohkem ekraanikuvasid"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopeerige rakenduste ikoonid"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Kas importida vanade avaekraanide ikoonid ja kaustad?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPEERI IKOONID"</string>
+    <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>
@@ -114,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 3a0d0b8..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,23 +77,29 @@
     <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>
-    <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="7257389003637362144">"خوش آمدید!"</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="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>
@@ -114,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 d327250..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Aloitusruutu %1$d/%2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-sivu %1$d / %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgetit-sivu %1$d / %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Tervetuloa!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Tervetuloa"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Ole kuin kotonasi."</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">"Luo lisää ruutuja sovelluksille ja kansioille"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopioi sovelluskuvakkeet"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Tuodaanko kuvakkeet ja kansiot vanhoista aloitusruuduista?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIOI KUVAKKEET"</string>
+    <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>
@@ -114,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 9d8dbeb..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Page des applications : %1$d sur %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Page des widgets : %1$d sur %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Bienvenue!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Faites comme chez vous."</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">"Créer plus d\'écrans pour les applications et les dossiers"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copier les icônes de vos applis"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importer les icônes et dossiers des anciens écrans d\'accueil?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIER LES ICÔNES"</string>
+    <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>
@@ -114,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 b1b0a79..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Page des applications %1$d sur %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Page des widgets %1$d sur %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Bienvenue !"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Familiarisez-vous avec l\'écran d\'accueil."</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">"Créez des écrans personnalisés pour vos applis et dossiers"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copier les icônes de vos applis"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importer les icônes et dossiers des anciens écrans d\'accueil ?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIER LES ICÔNES"</string>
+    <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>
@@ -114,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 eddd75c..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,66 +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="7257389003637362144">"स्वागत है!"</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>
@@ -114,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 783946d..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Početni zaslon %1$d od %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stranica aplikacija %1$d od %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stranica widgeta %1$d od %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Dobro došli!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Dobro došli"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Osjećajte se kao kod kuće."</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">"Izradite više zaslona za aplikacije i mape"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiranje ikona aplikacija"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Želite li uvesti ikone i mape sa starih početnih zaslona?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJ IKONE"</string>
+    <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>
@@ -114,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 8876652..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d/%1$d. kezdőképernyő"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d/%1$d. alkalmazásoldal"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d/%1$d. moduloldal"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Üdvözöljük!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Üdvözöljük!"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Varázsolja egyedivé készülékét."</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">"Hozzon létre további képernyőket az alkalmazásoknak és mappáknak"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Alkalmazásikonok másolása"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importálja ikonjait és mappáit régi kezdőképernyőiről?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"IKONOK MÁSOLÁSA"</string>
+    <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>
@@ -114,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 ab7388a..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Բարի գալուստ:"</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="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>
@@ -114,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 e1e93f7..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Layar utama %1$d dari %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Laman aplikasi %1$d dari %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Laman widget %1$d dari %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Selamat datang!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Selamat Datang"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Serasa di rumah sendiri."</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">"Buat lebih banyak layar untuk aplikasi dan folder"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Salin ikon aplikasi Anda"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Impor ikon dan folder dari layar Utama lama Anda?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"IKON SALIN"</string>
+    <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>
@@ -114,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 d5ada8f..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Schermata Home %1$d di %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pagina di applicazioni %1$d di %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pagina di widget %1$d di %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Benvenuto!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Benvenuto"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Personalizza la schermata Home."</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">"Creare più schermate per app e cartelle"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copia le icone delle tue app"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importare icone e cartelle dalle schermate Home precedenti?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIA ICONE"</string>
+    <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>
@@ -114,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 603dbb5..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,23 +77,29 @@
     <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>
-    <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="7257389003637362144">"ברוך הבא!"</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="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>
@@ -114,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 6e39c54..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"ようこそ!"</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="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>
@@ -114,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 a2e3374..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"კეთილი იყოს თქვენი მობრძანება!"</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="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>
@@ -114,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 977b2dd..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"សូម​ស្វាគមន៍​!"</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="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>
@@ -114,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 31c2d69..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"환영합니다!"</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="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>
@@ -114,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/config.xml b/res/values-land/config.xml
index 121bb0c..31115c9 100644
--- a/res/values-land/config.xml
+++ b/res/values-land/config.xml
@@ -18,6 +18,4 @@
 <!-- Workspace -->
     <!-- Whether or not the drop targets drop down as opposed to fade in -->
     <bool name="config_useDropTargetDownTransition">false</bool>
-    <!-- Whether or not to fade the side pages -->
-    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
 </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 ccb5fcb..87a7444 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -19,15 +19,11 @@
 
 <resources>
 <!-- Search Bar -->
-    <style name="QSBBar">
-    </style>
-    <style name="SearchDropTargetBar">
-    </style>
     <style name="SearchButton">
     </style>
     <style name="DropTargetButtonContainer">
         <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">0dp</item>
+        <item name="android:layout_height">wrap_content</item>
     </style>
     <style name="DropTargetButton">
         <item name="android:layout_width">wrap_content</item>
@@ -36,8 +32,8 @@
         <item name="android:gravity">center</item>
         <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
         <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
-        <item name="android:paddingStart">@dimen/toolbar_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
         <item name="android:shadowColor">#DD000000</item>
         <item name="android:shadowDx">0.0</item>
         <item name="android:shadowDy">1.0</item>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index e3a95dd..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>
@@ -96,17 +86,22 @@
     <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="7257389003637362144">"ຍິນດີຕ້ອນຮັບ!"</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="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>
@@ -114,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 80d4412..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d pagrindinis ekranas iš %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d programų psl. iš %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d valdiklių psl. iš %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Sveiki!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Sveiki"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Jauskitės kaip namie."</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">"Sukurkite daugiau programų ir aplankų ekrano kopijų"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Programų piktogramų kopij."</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importuoti piktogramas ir aplankus iš senų pagr. ekranų?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIJUOTI PIKTOGRAMAS"</string>
+    <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>
@@ -114,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 b70f5dc..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Sākuma ekrāns: %1$d no %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d. lietotņu lapa no %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d. logrīku lapa no %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Laipni lūdzam!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Laipni lūdzam!"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Informācija par pamatfunkcijām"</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">"Izveidojiet vairāk ekrānu lietotnēm un mapēm."</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Lietotņu ikonu kopēšana"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Vai importēt ikonas, mapes no iepriekšējiem sākuma ekrāniem?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPĒT IKONAS"</string>
+    <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>
@@ -114,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 7cf7a9c..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>
@@ -96,15 +86,20 @@
     <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="7257389003637362144">"Тавтай морилно уу!"</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="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>
@@ -114,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 4ee3545..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Skrin Laman Utama %1$d daripada %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Halaman apl %1$d daripada %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Halaman widget %1$d daripada %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Selamat datang!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Selamat datang"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Buat seperti berada di rumah sendiri."</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">"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 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>
@@ -114,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 ce50754..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Startside %1$d av %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Appside %1$d av %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Modulside %1$d av %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Velkommen!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Føl deg som hjemme."</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">"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 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>
@@ -114,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 e2a2a07..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Startscherm %1$d van %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"App-pagina %1$d van %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgetpagina %1$d van %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Welkom!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Personaliseer uw startscherm."</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">"Meer schermen maken voor apps en mappen"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Uw app-pictogrammen kopiëren"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Pictogrammen en mappen importeren uit uw oude startschermen?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"PICTOGRAMMEN KOPIËREN"</string>
+    <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>
@@ -114,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 b629f3d..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Ekran główny %1$d z %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Strona aplikacji: %1$d z %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Strona widżetów: %1$d z %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Witamy"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Witamy"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Poczuj się jak u siebie."</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">"Dodaj więcej ekranów na aplikacje i foldery"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiuj ikony aplikacji"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Zaimportować ikony i foldery ze starych ekranów głównych?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIUJ IKONY"</string>
+    <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>
@@ -114,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 1ef3982..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Ecrã principal %1$d de %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicações %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="7257389003637362144">"Bem-vindo(a)!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo(a)"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Sinta-se em 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">"Crie mais ecrãs para aplicações e pastas"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copiar ícones das aplicações"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Importar ícones e pastas dos ecrãs principais antigos?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONES"</string>
+    <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>
@@ -114,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 4d40388..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,64 +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="7257389003637362144">"Bem-vindo!"</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="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>
@@ -114,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 ddcf404..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 />
@@ -165,7 +148,7 @@
     <skip />
     <!-- no translation found for apps_customize_widgets_scroll_format (3106209519974971521) -->
     <skip />
-    <!-- no translation found for first_run_cling_title (7257389003637362144) -->
+    <!-- no translation found for first_run_cling_title (2459738000155917941) -->
     <skip />
     <!-- no translation found for first_run_cling_description (6447072552696253358) -->
     <skip />
@@ -173,14 +156,18 @@
     <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
     <!-- no translation found for first_run_cling_create_screens_hint (6950729526680114157) -->
     <skip />
+    <!-- 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 />
     <!-- no translation found for workspace_cling_title (5626202359865825661) -->
     <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) -->
@@ -199,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 78d9da4..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Ecranul de pornire %1$d din %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pagina de aplicații %1$d din %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pagina de widgeturi %1$d din %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Bun venit!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Bun venit"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Simțiți-vă ca acasă."</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ți mai multe ecrane pentru aplicații și dosare"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Copiați pictogr. aplicațiilor"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Import. pictogr. și dosare de pe ecranele de pornire anter.?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAȚI PICTOGRAMELE"</string>
+    <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>
@@ -114,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 06fbd26..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Добро пожаловать!"</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="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>
@@ -114,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 29de526..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Vitajte!"</string>
+    <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>
+    <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>
@@ -114,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 021eca8..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Začetni zaslon %1$d od %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stran aplikacij %1$d od %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stran pripomočkov %1$d od %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Pozdravljeni!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Pozdravljeni"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Počutite se kot 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">"Ustvarite več zaslonov za aplikacije in mape"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiranje ikon aplikacij"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Želite uvoziti ikone in mape iz starih začetnih zaslonov?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJ IKONE"</string>
+    <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>
@@ -114,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 06d80ef..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Добро дошли!"</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="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>
@@ -114,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 bf75200..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>
@@ -96,17 +86,22 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Startskärmen %1$d av %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Appsida %1$d av %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widget-sida %1$d av %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Välkommen!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Välkommen"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Känn dig som hemma."</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">"Skapa fler skärmar för appar och mappar"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopiera appikoner"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Vill du importera ikoner och mappar från gamla startskärmar?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIERA IKONER"</string>
+    <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">"Om du vill skapa en till mapp av det här slaget trycker du länge på en app och drar den sedan ovanpå en annan."</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>
     <string name="folder_opened" msgid="94695026776264709">"Mappen är öppen, <xliff:g id="WIDTH">%1$d</xliff:g> gånger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"Tryck om du vill stänga mappen"</string>
@@ -114,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 606a80d..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>
@@ -98,16 +88,21 @@
     <skip />
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ukurasa wa programu %1$d ya %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Ukurasa wa wijeti %1$d ya %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Karibu!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Karibu"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Jisikie huru."</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">"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 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>
@@ -116,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-port/config.xml b/res/values-sw340dp-port/config.xml
index d31ee59..5f71077 100644
--- a/res/values-sw340dp-port/config.xml
+++ b/res/values-sw340dp-port/config.xml
@@ -15,7 +15,4 @@
 -->
 
 <resources>
-<!-- Workspace -->
-    <!-- Whether or not to fade the side pages -->
-    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
 </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 3754304..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:paddingStart">35dp</item>
-        <item name="android:paddingEnd">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/config.xml b/res/values-sw720dp/config.xml
index 4f537a9..c00b594 100644
--- a/res/values-sw720dp/config.xml
+++ b/res/values-sw720dp/config.xml
@@ -9,8 +9,6 @@
 <!-- Workspace -->
     <!-- Whether or not the drop targets drop down as opposed to fade in -->
     <bool name="config_useDropTargetDownTransition">false</bool>
-    <!-- Whether or not to fade the side pages -->
-    <bool name="config_workspaceFadeAdjacentScreens">true</bool>
 
     <!-- Camera distance for the overscroll effect -->
     <integer name="config_cameraDistance">18000</integer>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 01227e1..8be9964 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -21,12 +21,13 @@
     <dimen name="toolbar_button_vertical_padding">8dip</dimen>
     <dimen name="toolbar_button_horizontal_padding">8dip</dimen>
 
-    <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
-    <dimen name="wallpaper_chooser_grid_width">196dp</dimen>
-    <dimen name="wallpaper_chooser_grid_height">140dp</dimen>
-
     <!-- When dragging items on the workspace, the number of dps by which the position of
      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 9738a12..71f0304 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -18,57 +18,14 @@
 -->
 
 <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:paddingStart">35dp</item>
-        <item name="android:paddingEnd">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="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>
-
     <style name="TabIndicator.AppsCustomize">
-        <item name="android:paddingStart">32dp</item>
-        <item name="android:paddingEnd">32dp</item>
+        <item name="android:paddingLeft">32dp</item>
+        <item name="android:paddingRight">32dp</item>
         <item name="android:textSize">14sp</item>
         <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">
@@ -81,8 +38,8 @@
         <item name="android:layout_gravity">center</item>
         <item name="android:gravity">center_vertical</item>
         <item name="android:drawablePadding">7.5dp</item>
-        <item name="android:paddingStart">60dp</item>
-        <item name="android:paddingEnd">60dp</item>
+        <item name="android:paddingLeft">60dp</item>
+        <item name="android:paddingRight">60dp</item>
         <item name="android:textColor">#FFFFFFFF</item>
         <item name="android:textSize">16sp</item>
         <item name="android:shadowColor">#393939</item>
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 68118a7..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"ยินดีต้อนรับ!"</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="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>
@@ -114,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 56801b4..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d ng %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pahina ng apps %1$d ng %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pahina ng widget %1$d ng %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Maligayang pagdating!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Maligayang Pagdating"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Gawing kumportable ang iyong sarili."</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">"Gumawa ng higit pang mga screen para sa apps at mga folder"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopyahin ang mga icon ng app"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"I-import ang icon at folder mula sa luma mong Home screen?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPYAHIN ANG MGA ICON"</string>
+    <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>
@@ -114,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 dbbdee2..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Hoş geldiniz!"</string>
+    <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>
+    <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>
@@ -114,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 e0f3211..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Вітаємо!"</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="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>
@@ -114,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-v17/styles.xml b/res/values-v17/styles.xml
new file mode 100644
index 0000000..71c4bfa
--- /dev/null
+++ b/res/values-v17/styles.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="PagedViewWidgetImageView">
+        <item name="android:paddingStart">@dimen/app_widget_preview_padding_left</item>
+    </style>
+    <style name="SearchButton.WithPaddingStart">
+        <item name="android:paddingStart">8dp</item>
+    </style>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 3b081d0..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Màn hình chính %1$d / %2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Trang ứng dụng %1$d / %2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Trang tiện ích con %1$d / %2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Xin chào!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Chào mừng"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Tự nhiên như ở nhà."</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">"Tạo thêm màn hình cho ứng dụng và thư mục"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Sao chép biểu tượng ứng dụng của bạn"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Nhập biểu tượng và thư mục từ Màn hình chính cũ của bạn?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"BIỂU TƯỢNG SAO CHÉP"</string>
+    <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>
@@ -114,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 43a57c4..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,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"欢迎!"</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="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>
@@ -114,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 eb3def4..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"歡迎!"</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="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>
@@ -114,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 a68f163..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>
@@ -96,15 +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>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"歡迎使用!"</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="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>
@@ -114,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 da790e6..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>
@@ -96,15 +86,20 @@
     <string name="workspace_scroll_format" msgid="8458889198184077399">"Isikrini sasekhaya esingu-%1$d se-%2$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ikhasi lezinhlelo zokusebenza elingu-%1$d le-%2$d"</string>
     <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Ikhasi lamawijethi elingu-%1$d le-%2$d"</string>
-    <string name="first_run_cling_title" msgid="7257389003637362144">"Siyakwamukela!"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Siyakwamukela"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"Zizwe usekhaya."</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">"Dala izikrini eziningi zezinhlelo zokusebenza namafolda"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopisha izithonjana zakho zohlelo lokusebenza"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Ngenisa izithonjana namafolda kusukela kuzikrini zakho ezindala zasekhaya?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPISHA IZITHONJANA"</string>
+    <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>
@@ -114,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 c073903..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,11 +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="wallpaper_picker_translucent_gray">#66000000</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 1538d9f..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>
 
@@ -52,8 +62,6 @@
 <!-- Workspace -->
     <!-- Whether or not the drop targets drop down as opposed to fade in -->
     <bool name="config_useDropTargetDownTransition">false</bool>
-    <!-- Whether or not to fade the side pages -->
-    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
 
     <!-- The transition duration for the background of the drop targets -->
     <integer name="config_dropTargetBgTransitionDuration">0</integer>
@@ -71,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>
@@ -83,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>
 
@@ -96,4 +103,7 @@
          filter the activities shown in the launcher. Can be empty. -->
     <string name="app_filter_class" translatable="false"></string>
 
+    <!-- Name of a subclass of com.android.launcher3.BuildInfo used to
+         get build information. Can be empty. -->
+    <string name="build_info_class" translatable="false"></string>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c86fe31..2c9e689 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -18,36 +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>
-
-<!-- Wallpaper picker -->
-    <dimen name="wallpaperThumbnailWidth">106.5dp</dimen>
-    <dimen name="wallpaperThumbnailHeight">94.5dp</dimen>
-    <dimen name="wallpaperItemIconSize">32dp</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>
@@ -66,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>
@@ -92,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>
@@ -105,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 30f4d8f..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 -->
@@ -28,40 +38,10 @@
     <string name="uid_name">Android Core Apps</string>
     <!-- Default folder name -->
     <string name="folder_name"></string>
-    <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
-    <string name="wallpaper_instructions">Set wallpaper</string>
-    <!-- Error message when an image is selected as a wallpaper,
-         but the wallpaper picker cannot load it -->
-    <string name="image_load_fail">Coudn\'t load image</string>
-    <!-- Error message when an image is selected as a wallpaper,
-         but the wallpaper cropper cannot load it. The user will
-         usually see this when using another app and trying to set
-         an image as the wallpaper -->
-    <string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
-    <!-- Shown when wallpapers are selected in Wallpaper picker -->
-    <!-- String indicating how many media item(s) is(are) selected
-            eg. 1 selected [CHAR LIMIT=30] -->
-    <plurals name="number_of_items_selected">
-        <item quantity="zero">%1$d selected</item>
-        <item quantity="one">%1$d selected</item>
-        <item quantity="other">%1$d selected</item>
-    </plurals>
-    <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list.
-         e.g. "Wallpaper 3 of 10" -->
-    <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string>
-    <!-- Accessibility string used to announce that a wallpaper has been selected. -->
-    <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string>
-
-    <!-- Label on button to delete wallpaper(s) -->
-    <string name="wallpaper_delete">Delete</string>
-    <!-- Label on button in Wallpaper Picker to pick an image -->
-    <string name="pick_image">Pick image</string>
-    <!-- Option in "Select wallpaper from" dialog box -->
-    <string name="pick_wallpaper">Wallpapers</string>
-    <!-- Title of activity for cropping wallpapers -->
-    <string name="crop_wallpaper">Crop wallpaper</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>
 
@@ -117,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 -->
@@ -213,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>
 
@@ -239,7 +222,7 @@
 
     <!-- Clings -->
     <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
-    <string name="first_run_cling_title">Welcome!</string>
+    <string name="first_run_cling_title">Welcome</string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
     <string name="first_run_cling_description">Make yourself at home.</string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
@@ -248,10 +231,24 @@
     <string name="first_run_cling_search_bar_hint"></string>
     <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
     <string name="first_run_cling_create_screens_hint">Create more screens for apps and folders</string>
+    <!-- The title text for the migration cling [CHAR_LIMIT=30] -->
+    <string name="migration_cling_title">Copy your app icons</string>
+    <!-- The description of what migration does [CHAR_LIMIT=70] -->
+    <string name="migration_cling_description">Import icons and folders from your old Home screens?</string>
+    <!-- The description of the button to migrate apps from another launcher [CHAR_LIMIT=30] -->
+    <string name="migration_cling_copy_apps">COPY ICONS</string>
+    <!-- The description of the button to use the default launcher layout [CHAR_LIMIT=30] -->
+    <string name="migration_cling_use_default">START FRESH</string>
     <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
     <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] -->
@@ -276,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>
 
@@ -298,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 8226915..56a205f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,70 +18,6 @@
 -->
 
 <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="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
-        <item name="android:displayOptions">showCustom</item>
-        <item name="android:background">#88000000</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>
-
-    <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:paddingStart">50dp</item>
-        <item name="android:paddingEnd">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>
@@ -103,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">
@@ -126,8 +66,8 @@
         <item name="android:layout_gravity">center</item>
         <item name="android:gravity">center_vertical</item>
         <item name="android:drawablePadding">7.5dp</item>
-        <item name="android:paddingStart">25dp</item>
-        <item name="android:paddingEnd">25dp</item>
+        <item name="android:paddingLeft">25dp</item>
+        <item name="android:paddingRight">25dp</item>
         <item name="android:textColor">#FFFFFFFF</item>
         <item name="android:textSize">16sp</item>
         <item name="android:singleLine">true</item>
@@ -142,8 +82,8 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingStart">20dp</item>
-        <item name="android:paddingEnd">20dp</item>
+        <item name="android:paddingLeft">20dp</item>
+        <item name="android:paddingRight">20dp</item>
         <item name="android:background">@drawable/tab_widget_indicator_selector</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">12sp</item>
@@ -157,8 +97,8 @@
     </style>
 
     <style name="MarketButton">
-        <item name="android:paddingStart">5dp</item>
-        <item name="android:paddingEnd">5dp</item>
+        <item name="android:paddingLeft">5dp</item>
+        <item name="android:paddingRight">5dp</item>
         <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
         <item name="android:textSize">18sp</item>
         <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
@@ -167,9 +107,23 @@
         <item name="android:shadowRadius">2.0</item>
     </style>
 
-    <!-- Overridden in device overlays -->
-    <style name="CustomClingTitleText">
+    <style name="PreloadIcon">
+        <item name="background">@drawable/virtual_preload</item>
+        <item name="indicatorSize">4dp</item>
+        <item name="ringOutset">4dp</item>
     </style>
-    <style name="CustomClingText">
+
+    <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="PagedViewWidgetImageView">
+        <item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item>
+    </style>
+    <style name="SearchButton.WithPaddingStart">
+        <item name="android:paddingLeft">8dp</item>
     </style>
 </resources>
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_4x4_no_all_apps.xml b/res/xml/default_workspace_4x4_no_all_apps.xml
new file mode 100644
index 0000000..7e1301c
--- /dev/null
+++ b/res/xml/default_workspace_4x4_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="0"
+        launcher:x="0"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.talk"
+        launcher:className="com.google.android.talk.SigningInActivity"
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.apps.maps"
+        launcher:className="com.google.android.maps.MapsActivity"
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0"/>
+    <favorite
+        launcher:packageName="com.android.chrome"
+        launcher:className="com.google.android.apps.chrome.Main"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.GoogleCamera"
+        launcher:className="com.android.camera.CameraLauncher"
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" />
+</favorites>
+
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 ad15e75..0000000
--- a/src/com/android/launcher3/AddAdapter.java
+++ /dev/null
@@ -1,103 +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;
-
-import com.android.launcher3.R;
-
-/**
- * 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/Alarm.java b/src/com/android/launcher3/Alarm.java
index 91f9bd0..e9f1fd9 100644
--- a/src/com/android/launcher3/Alarm.java
+++ b/src/com/android/launcher3/Alarm.java
@@ -78,7 +78,3 @@
         return mAlarmPending;
     }
 }
-
-interface OnAlarmListener {
-    public void onAlarm(Alarm alarm);
-}
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index d955e4e..38d2fa5 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -16,9 +16,6 @@
 
 package com.android.launcher3;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -26,13 +23,20 @@
 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;
+
 
 /**
  * Stores the list of all applications for the all apps view.
  */
 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 53f81bb..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.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageInfo;
+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/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index fcb04ea..f57f4d0 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -13,8 +13,6 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
-import com.android.launcher3.R;
-
 public class AppWidgetResizeFrame extends FrameLayout {
     private LauncherAppWidgetHostView mWidgetView;
     private CellLayout mCellLayout;
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 688ff82..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,42 +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);
-
-    public static boolean DISABLE_ALL_APPS = false;
-
     // Previews & outlines
     ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
     private static final int sPageSleepDelay = 200;
@@ -215,6 +195,7 @@
     int mWidgetLoadingId = -1;
     PendingAddWidgetInfo mCreateWidgetInfo = null;
     private boolean mDraggingWidget = false;
+    boolean mPageBackgroundsVisible = true;
 
     private Toast mWidgetInstructionToast;
 
@@ -225,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;
@@ -250,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());
 
@@ -273,6 +235,7 @@
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+        setSinglePageInViewport();
     }
 
     @Override
@@ -297,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
@@ -366,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();
@@ -387,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 ((DISABLE_ALL_APPS || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
-                setDataIsReady();
-                setMeasuredDimension(width, height);
-                onDataReady(width, height);
+            if ((LauncherAppState.isDisableAllApps() || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
+                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) {
@@ -449,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);
@@ -499,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) {
@@ -548,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;
     }
@@ -590,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;
                 }
             }
         };
@@ -729,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
@@ -748,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;
         }
 
@@ -782,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)) {
@@ -797,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();
                 }
@@ -816,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);
         }
@@ -916,6 +820,16 @@
     }
 
     @Override
+    public boolean supportsAppInfoDropTarget() {
+        return true;
+    }
+
+    @Override
+    public boolean supportsDeleteDropTarget() {
+        return false;
+    }
+
+    @Override
     public float getIntrinsicIconScaleFactor() {
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -1008,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();
@@ -1028,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;
@@ -1139,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,
@@ -1157,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;
@@ -1180,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);
@@ -1200,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) {
@@ -1210,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);
@@ -1221,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);
         }
 
@@ -1247,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 {
@@ -1288,7 +1231,7 @@
                 task.syncThreadPriority();
             }
 
-            images.add(mWidgetPreviewLoader.getPreview(items.get(i)));
+            images.add(getWidgetPreviewLoader().getPreview(items.get(i)));
         }
     }
 
@@ -1378,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();
     }
 
@@ -1502,7 +1366,7 @@
     }
 
     protected void overScroll(float amount) {
-        acceleratedOverScroll(amount);
+        dampedOverScroll(amount);
     }
 
     /**
@@ -1548,7 +1412,7 @@
     }
 
     public void setApps(ArrayList<AppInfo> list) {
-        if (!DISABLE_ALL_APPS) {
+        if (!LauncherAppState.isDisableAllApps()) {
             mApps = list;
             Collections.sort(mApps, LauncherModel.getAppNameComparator());
             updatePageCountsAndInvalidateData();
@@ -1566,7 +1430,7 @@
         }
     }
     public void addApps(ArrayList<AppInfo> list) {
-        if (!DISABLE_ALL_APPS) {
+        if (!LauncherAppState.isDisableAllApps()) {
             addAppsWithoutInvalidate(list);
             updatePageCountsAndInvalidateData();
         }
@@ -1576,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;
             }
         }
@@ -1594,7 +1459,7 @@
         }
     }
     public void removeApps(ArrayList<AppInfo> appInfos) {
-        if (!DISABLE_ALL_APPS) {
+        if (!LauncherAppState.isDisableAllApps()) {
             removeAppsWithoutInvalidate(appInfos);
             updatePageCountsAndInvalidateData();
         }
@@ -1603,7 +1468,7 @@
         // We remove and re-add the updated applications list because it's properties may have
         // changed (ie. the title), and this will ensure that the items will be in their proper
         // place in the list.
-        if (!DISABLE_ALL_APPS) {
+        if (!LauncherAppState.isDisableAllApps()) {
             removeAppsWithoutInvalidate(list);
             addAppsWithoutInvalidate(list);
             updatePageCountsAndInvalidateData();
@@ -1614,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) {
@@ -1663,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.
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
index 697bd7e..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.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 30016e5..a368796 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,17 +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.Color;
-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;
 
 /**
@@ -36,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();
     }
 
@@ -88,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) {
@@ -138,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
@@ -232,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();
@@ -255,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;
     }
@@ -267,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;
         }
@@ -343,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
@@ -358,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) {
@@ -380,10 +367,6 @@
 
     @Override
     protected boolean onSetAlpha(int alpha) {
-        if (mPrevAlpha != alpha) {
-            mPrevAlpha = alpha;
-            super.onSetAlpha(alpha);
-        }
         return true;
     }
 
@@ -393,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/BuildInfo.java b/src/com/android/launcher3/BuildInfo.java
new file mode 100644
index 0000000..b49ee0d
--- /dev/null
+++ b/src/com/android/launcher3/BuildInfo.java
@@ -0,0 +1,32 @@
+package com.android.launcher3;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class BuildInfo {
+    private static final boolean DBG = false;
+    private static final String TAG = "BuildInfo";
+
+    public boolean isDogfoodBuild() {
+        return false;
+    }
+
+    public static BuildInfo loadByName(String className) {
+        if (TextUtils.isEmpty(className)) return new BuildInfo();
+
+        if (DBG) Log.d(TAG, "Loading BuildInfo: " + className);
+        try {
+            Class<?> cls = Class.forName(className);
+            return (BuildInfo) cls.newInstance();
+        } catch (ClassNotFoundException e) {
+            Log.e(TAG, "Bad BuildInfo class", e);
+        } catch (InstantiationException e) {
+            Log.e(TAG, "Bad BuildInfo class", e);
+        } catch (IllegalAccessException e) {
+            Log.e(TAG, "Bad BuildInfo class", e);
+        } catch (ClassCastException e) {
+            Log.e(TAG, "Bad BuildInfo class", e);
+        }
+        return new BuildInfo();
+    }
+}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index d51ae46..019f86c 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -25,8 +25,6 @@
 import android.view.View;
 import android.widget.TextView;
 
-import com.android.launcher3.R;
-
 
 /**
  * Implements a DropTarget.
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index df16d41..0ff1ef4 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -30,12 +30,9 @@
 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;
-import android.graphics.drawable.NinePatchDrawable;
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -48,7 +45,6 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LayoutAnimationController;
 
-import com.android.launcher3.R;
 import com.android.launcher3.FolderIcon.FolderRingAnimator;
 
 import java.util.ArrayList;
@@ -75,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.
@@ -100,6 +93,7 @@
     private int mForegroundAlpha = 0;
     private float mBackgroundAlpha;
     private float mBackgroundAlphaMultiplier = 1.0f;
+    private boolean mDrawBackground = true;
 
     private Drawable mNormalBackground;
     private Drawable mActiveGlowBackground;
@@ -129,12 +123,12 @@
     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>();
-    private HashMap<View, ReorderHintAnimation>
-            mShakeAnimators = new HashMap<View, ReorderHintAnimation>();
+    private HashMap<View, ReorderPreviewAnimation>
+            mShakeAnimators = new HashMap<View, ReorderPreviewAnimation>();
 
     private boolean mItemPlacementDirty = false;
 
@@ -149,19 +143,20 @@
     private boolean mIsHotseat = false;
     private float mHotseatScale = 1f;
 
-    public static final int MODE_DRAG_OVER = 0;
-    public static final int MODE_ON_DROP = 1;
-    public static final int MODE_ON_DROP_EXTERNAL = 2;
-    public static final int MODE_ACCEPT_DROP = 3;
+    public static final int MODE_SHOW_REORDER_HINT = 0;
+    public static final int MODE_DRAG_OVER = 1;
+    public static final int MODE_ON_DROP = 2;
+    public static final int MODE_ON_DROP_EXTERNAL = 3;
+    public static final int MODE_ACCEPT_DROP = 4;
     private static final boolean DESTRUCTIVE_REORDER = false;
     private static final boolean DEBUG_VISUALIZE_OCCUPIED = false;
 
     static final int LANDSCAPE = 0;
     static final int PORTRAIT = 1;
 
-    private static final float REORDER_HINT_MAGNITUDE = 0.12f;
+    private static final float REORDER_PREVIEW_MAGNITUDE = 0.12f;
     private static final int REORDER_ANIMATION_DURATION = 150;
-    private float mReorderHintAnimationMagnitude;
+    private float mReorderPreviewAnimationMagnitude;
 
     private ArrayList<View> mIntersectingViews = new ArrayList<View>();
     private Rect mOccupiedRect = new Rect();
@@ -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) {
@@ -199,7 +192,7 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
 
         mCellWidth = mCellHeight = -1;
-        mFixedCellHeight = mFixedCellHeight = -1;
+        mFixedCellWidth = mFixedCellHeight = -1;
         mWidthGap = mOriginalWidthGap = 0;
         mHeightGap = mOriginalHeightGap = 0;
         mMaxGap = Integer.MAX_VALUE;
@@ -225,7 +218,7 @@
         mForegroundPadding =
                 res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);
 
-        mReorderHintAnimationMagnitude = (REORDER_HINT_MAGNITUDE *
+        mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE *
                 grid.iconSizePx);
 
         mNormalBackground.setFilterBitmap(true);
@@ -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,17 +350,40 @@
         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);
+    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();
+            }
         }
-        if (mPressedOrFocusedIcon != null) {
-            invalidateBubbleTextView(mPressedOrFocusedIcon);
-        }
+    }
+
+    void setUseActiveGlowBackground(boolean use) {
+        mUseActiveGlowBackground = use;
+    }
+
+    void disableBackground() {
+        mDrawBackground = false;
+    }
+
+    void disableDragTarget() {
+        mIsDragTarget = false;
+    }
+
+    boolean isDragTarget() {
+        return mIsDragTarget;
     }
 
     void setIsDragOverlapping(boolean isDragOverlapping) {
@@ -383,31 +394,10 @@
         }
     }
 
-    void setUseActiveGlowBackground(boolean use) {
-        mUseActiveGlowBackground = use;
-    }
-
     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
@@ -415,7 +405,7 @@
         // When we're small, we are either drawn normally or in the "accepts drops" state (during
         // a drag). However, we also drag the mini hover background *over* one of those two
         // backgrounds
-        if (mBackgroundAlpha > 0.0f) {
+        if (mDrawBackground && mBackgroundAlpha > 0.0f) {
             Drawable bg;
 
             if (mUseActiveGlowBackground) {
@@ -443,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);
@@ -578,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
@@ -695,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
@@ -1045,6 +940,7 @@
     }
 
     public void setBackgroundAlphaMultiplier(float multiplier) {
+
         if (mBackgroundAlphaMultiplier != multiplier) {
             mBackgroundAlphaMultiplier = multiplier;
             invalidate();
@@ -1063,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) {
@@ -2088,6 +1978,8 @@
             }
         }
 
+        solution.intersectingViews = new ArrayList<View>(mIntersectingViews);
+
         // First we try to find a solution which respects the push mechanic. That is,
         // we try to find a solution such that no displaced item travels through another item
         // without also displacing that item.
@@ -2136,8 +2028,9 @@
         }
     }
 
-    ItemConfiguration simpleSwap(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
-            int spanY, int[] direction, View dragView, boolean decX, ItemConfiguration solution) {
+    ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY,
+            int spanX, int spanY, int[] direction, View dragView, boolean decX,
+            ItemConfiguration solution) {
         // Copy the current state into the solution. This solution will be manipulated as necessary.
         copyCurrentStateToSolution(solution, false);
         // Copy the current occupied array into the temporary occupied array. This array will be
@@ -2159,11 +2052,11 @@
             // We try shrinking the widget down to size in an alternating pattern, shrink 1 in
             // x, then 1 in y etc.
             if (spanX > minSpanX && (minSpanY == spanY || decX)) {
-                return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, direction,
-                        dragView, false, solution);
+                return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY,
+                        direction, dragView, false, solution);
             } else if (spanY > minSpanY) {
-                return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, direction,
-                        dragView, true, solution);
+                return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1,
+                        direction, dragView, true, solution);
             }
             solution.isSolution = false;
         } else {
@@ -2243,25 +2136,30 @@
         }
     }
 
-    // This method starts or changes the reorder hint animations
-    private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
+
+    // This method starts or changes the reorder preview animations
+    private void beginOrAdjustReorderPreviewAnimations(ItemConfiguration solution,
+            View dragView, int delay, int mode) {
         int childCount = mShortcutsAndWidgets.getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = mShortcutsAndWidgets.getChildAt(i);
             if (child == dragView) continue;
             CellAndSpan c = solution.map.get(child);
+            boolean skip = mode == ReorderPreviewAnimation.MODE_HINT && solution.intersectingViews
+                    != null && !solution.intersectingViews.contains(child);
+
             LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            if (c != null) {
-                ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
-                        c.x, c.y, c.spanX, c.spanY);
+            if (c != null && !skip) {
+                ReorderPreviewAnimation rha = new ReorderPreviewAnimation(child, mode, lp.cellX,
+                        lp.cellY, c.x, c.y, c.spanX, c.spanY);
                 rha.animate();
             }
         }
     }
 
-    // Class which represents the reorder hint animations. These animations show that an item is
+    // Class which represents the reorder preview animations. These animations show that an item is
     // in a temporary state, and hint at where the item will return to.
-    class ReorderHintAnimation {
+    class ReorderPreviewAnimation {
         View child;
         float finalDeltaX;
         float finalDeltaY;
@@ -2269,11 +2167,18 @@
         float initDeltaY;
         float finalScale;
         float initScale;
-        private static final int DURATION = 300;
+        int mode;
+        boolean repeating = false;
+        private static final int PREVIEW_DURATION = 300;
+        private static final int HINT_DURATION = Workspace.REORDER_TIMEOUT;
+
+        public static final int MODE_HINT = 0;
+        public static final int MODE_PREVIEW = 1;
+
         Animator a;
 
-        public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
-                int spanX, int spanY) {
+        public ReorderPreviewAnimation(View child, int mode, int cellX0, int cellY0, int cellX1,
+                int cellY1, int spanX, int spanY) {
             regionToCenterPoint(cellX0, cellY0, spanX, spanY, mTmpPoint);
             final int x0 = mTmpPoint[0];
             final int y0 = mTmpPoint[1];
@@ -2284,20 +2189,22 @@
             final int dY = y1 - y0;
             finalDeltaX = 0;
             finalDeltaY = 0;
+            int dir = mode == MODE_HINT ? -1 : 1;
             if (dX == dY && dX == 0) {
             } else {
                 if (dY == 0) {
-                    finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
+                    finalDeltaX = - dir * Math.signum(dX) * mReorderPreviewAnimationMagnitude;
                 } else if (dX == 0) {
-                    finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
+                    finalDeltaY = - dir * Math.signum(dY) * mReorderPreviewAnimationMagnitude;
                 } else {
                     double angle = Math.atan( (float) (dY) / dX);
-                    finalDeltaX = (int) (- Math.signum(dX) *
-                            Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
-                    finalDeltaY = (int) (- Math.signum(dY) *
-                            Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
+                    finalDeltaX = (int) (- dir * Math.signum(dX) *
+                            Math.abs(Math.cos(angle) * mReorderPreviewAnimationMagnitude));
+                    finalDeltaY = (int) (- dir * Math.signum(dY) *
+                            Math.abs(Math.sin(angle) * mReorderPreviewAnimationMagnitude));
                 }
             }
+            this.mode = mode;
             initDeltaX = child.getTranslationX();
             initDeltaY = child.getTranslationY();
             finalScale = getChildrenScale() - 4.0f / child.getWidth();
@@ -2307,7 +2214,7 @@
 
         void animate() {
             if (mShakeAnimators.containsKey(child)) {
-                ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
+                ReorderPreviewAnimation oldAnimation = mShakeAnimators.get(child);
                 oldAnimation.cancel();
                 mShakeAnimators.remove(child);
                 if (finalDeltaX == 0 && finalDeltaY == 0) {
@@ -2322,14 +2229,15 @@
             a = va;
             va.setRepeatMode(ValueAnimator.REVERSE);
             va.setRepeatCount(ValueAnimator.INFINITE);
-            va.setDuration(DURATION);
+            va.setDuration(mode == MODE_HINT ? HINT_DURATION : PREVIEW_DURATION);
             va.setStartDelay((int) (Math.random() * 60));
             va.addUpdateListener(new AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
                     float r = ((Float) animation.getAnimatedValue()).floatValue();
-                    float x = r * finalDeltaX + (1 - r) * initDeltaX;
-                    float y = r * finalDeltaY + (1 - r) * initDeltaY;
+                    float r1 = (mode == MODE_HINT && repeating) ? 1.0f : r;
+                    float x = r1 * finalDeltaX + (1 - r1) * initDeltaX;
+                    float y = r1 * finalDeltaY + (1 - r1) * initDeltaY;
                     child.setTranslationX(x);
                     child.setTranslationY(y);
                     float s = r * finalScale + (1 - r) * initScale;
@@ -2343,6 +2251,7 @@
                     initDeltaX = 0;
                     initDeltaY = 0;
                     initScale = getChildrenScale();
+                    repeating = true;
                 }
             });
             mShakeAnimators.put(child, this);
@@ -2374,8 +2283,8 @@
         }
     }
 
-    private void completeAndClearReorderHintAnimations() {
-        for (ReorderHintAnimation a: mShakeAnimators.values()) {
+    private void completeAndClearReorderPreviewAnimations() {
+        for (ReorderPreviewAnimation a: mShakeAnimators.values()) {
             a.completeAnimationImmediately();
         }
         mShakeAnimators.clear();
@@ -2518,20 +2427,21 @@
     }
 
     void revertTempState() {
-        if (!isItemPlacementDirty() || DESTRUCTIVE_REORDER) return;
-        final int count = mShortcutsAndWidgets.getChildCount();
-        for (int i = 0; i < count; i++) {
-            View child = mShortcutsAndWidgets.getChildAt(i);
-            LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
-                lp.tmpCellX = lp.cellX;
-                lp.tmpCellY = lp.cellY;
-                animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
-                        0, false, false);
+        completeAndClearReorderPreviewAnimations();
+        if (isItemPlacementDirty() && !DESTRUCTIVE_REORDER) {
+            final int count = mShortcutsAndWidgets.getChildCount();
+            for (int i = 0; i < count; i++) {
+                View child = mShortcutsAndWidgets.getChildAt(i);
+                LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
+                    lp.tmpCellX = lp.cellX;
+                    lp.tmpCellY = lp.cellY;
+                    animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
+                            0, false, false);
+                }
             }
+            setItemPlacementDirty(false);
         }
-        completeAndClearReorderHintAnimations();
-        setItemPlacementDirty(false);
     }
 
     boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY,
@@ -2540,7 +2450,7 @@
         regionToCenterPoint(cellX, cellY, spanX, spanY, pixelXY);
 
         // First we determine if things have moved enough to cause a different layout
-        ItemConfiguration swapSolution = simpleSwap(pixelXY[0], pixelXY[1], spanX, spanY,
+        ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
                  spanX,  spanY, direction, dragView,  true,  new ItemConfiguration());
 
         setUseTempCoords(true);
@@ -2554,18 +2464,18 @@
 
             if (commit) {
                 commitTempPlacement();
-                completeAndClearReorderHintAnimations();
+                completeAndClearReorderPreviewAnimations();
                 setItemPlacementDirty(false);
             } else {
-                beginOrAdjustHintAnimations(swapSolution, dragView,
-                        REORDER_ANIMATION_DURATION);
+                beginOrAdjustReorderPreviewAnimations(swapSolution, dragView,
+                        REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW);
             }
             mShortcutsAndWidgets.requestLayout();
         }
         return swapSolution.isSolution;
     }
 
-    int[] createArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
+    int[] performReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
             View dragView, int[] result, int resultSpan[], int mode) {
         // First we determine if things have moved enough to cause a different layout
         result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
@@ -2592,7 +2502,8 @@
             mPreviousReorderDirection[1] = mDirectionVector[1];
         }
 
-        ItemConfiguration swapSolution = simpleSwap(pixelX, pixelY, minSpanX, minSpanY,
+        // Find a solution involving pushing / displacing any items in the way
+        ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
                  spanX,  spanY, mDirectionVector, dragView,  true,  new ItemConfiguration());
 
         // We attempt the approach which doesn't shuffle views at all
@@ -2600,12 +2511,29 @@
                 minSpanY, spanX, spanY, dragView, new ItemConfiguration());
 
         ItemConfiguration finalSolution = null;
+
+        // If the reorder solution requires resizing (shrinking) the item being dropped, we instead
+        // favor a solution in which the item is not resized, but
         if (swapSolution.isSolution && swapSolution.area() >= noShuffleSolution.area()) {
             finalSolution = swapSolution;
         } else if (noShuffleSolution.isSolution) {
             finalSolution = noShuffleSolution;
         }
 
+        if (mode == MODE_SHOW_REORDER_HINT) {
+            if (finalSolution != null) {
+                beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, 0,
+                        ReorderPreviewAnimation.MODE_HINT);
+                result[0] = finalSolution.dragViewX;
+                result[1] = finalSolution.dragViewY;
+                resultSpan[0] = finalSolution.dragViewSpanX;
+                resultSpan[1] = finalSolution.dragViewSpanY;
+            } else {
+                result[0] = result[1] = resultSpan[0] = resultSpan[1] = -1;
+            }
+            return result;
+        }
+
         boolean foundSolution = true;
         if (!DESTRUCTIVE_REORDER) {
             setUseTempCoords(true);
@@ -2630,11 +2558,11 @@
                 if (!DESTRUCTIVE_REORDER &&
                         (mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) {
                     commitTempPlacement();
-                    completeAndClearReorderHintAnimations();
+                    completeAndClearReorderPreviewAnimations();
                     setItemPlacementDirty(false);
                 } else {
-                    beginOrAdjustHintAnimations(finalSolution, dragView,
-                            REORDER_ANIMATION_DURATION);
+                    beginOrAdjustReorderPreviewAnimations(finalSolution, dragView,
+                            REORDER_ANIMATION_DURATION,  ReorderPreviewAnimation.MODE_PREVIEW);
                 }
             }
         } else {
@@ -2661,6 +2589,7 @@
         HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>();
         private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>();
         ArrayList<View> sortedViews = new ArrayList<View>();
+        ArrayList<View> intersectingViews;
         boolean isSolution = false;
         int dragViewX, dragViewY, dragViewSpanX, dragViewSpanY;
 
@@ -3317,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 9974acd..0000000
--- a/src/com/android/launcher3/Cling.java
+++ /dev/null
@@ -1,446 +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.app.ActivityOptions;
-import android.content.Context;
-import android.content.ComponentName;
-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 {
-
-    static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
-    static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
-    static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
-
-    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 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 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 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);
-
-            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 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)) {
-            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)) {
-            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.dismissWorkspaceCling(this);
-            }
-        }
-    }
-
-    @Override
-    public boolean onLongClick(View v) {
-        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
-                mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
-                mDrawIdentifier.equals(WORKSPACE_LARGE)) {
-            mLauncher.dismissWorkspaceCling(null);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (mIsInitialized) {
-            canvas.save();
-
-            // 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)) {
-                // 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);
-                mErasePaint.setAlpha((int) (128));
-                eraseCanvas.drawCircle(metrics.widthPixels / 2,
-                        metrics.heightPixels / 2 - offset,
-                        DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
-                        mErasePaint);
-                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);
-                }
-            }
-
-            canvas.restore();
-        }
-
-        // Draw the rest of the cling
-        super.dispatchDraw(canvas);
-    };
-}
diff --git a/src/com/android/launcher3/DeferredHandler.java b/src/com/android/launcher3/DeferredHandler.java
index 92ecf96..a2d121d 100644
--- a/src/com/android/launcher3/DeferredHandler.java
+++ b/src/com/android/launcher3/DeferredHandler.java
@@ -21,6 +21,7 @@
 import android.os.Message;
 import android.os.MessageQueue;
 import android.util.Pair;
+
 import java.util.LinkedList;
 import java.util.ListIterator;
 
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 4023daf..05e8906 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -29,6 +29,10 @@
 import android.graphics.PointF;
 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;
@@ -37,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;
 
@@ -95,7 +102,7 @@
     }
 
     private boolean isAllAppsApplication(DragSource source, Object info) {
-        return (source instanceof AppsCustomizePagedView) && (info instanceof AppInfo);
+        return source.supportsAppInfoDropTarget() && (info instanceof AppInfo);
     }
     private boolean isAllAppsWidget(DragSource source, Object info) {
         if (source instanceof AppsCustomizePagedView) {
@@ -124,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);
     }
 
@@ -145,12 +156,12 @@
                 return true;
             }
 
-            if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+            if (!LauncherAppState.isDisableAllApps() &&
                     item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
                 return true;
             }
 
-            if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+            if (!LauncherAppState.isDisableAllApps() &&
                     item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
                     item instanceof AppInfo) {
                 AppInfo appInfo = (AppInfo) info;
@@ -159,7 +170,7 @@
 
             if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
                 item instanceof ShortcutInfo) {
-                if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+                if (LauncherAppState.isDisableAllApps()) {
                     ShortcutInfo shortcutInfo = (ShortcutInfo) info;
                     return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
                 } else {
@@ -173,8 +184,9 @@
     @Override
     public void onDragStart(DragSource source, Object info, int dragAction) {
         boolean isVisible = true;
-        boolean useUninstallLabel = !AppsCustomizePagedView.DISABLE_ALL_APPS &&
+        boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() &&
                 isAllAppsApplication(source, info);
+        boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget();
 
         // If we are dragging an application from AppsCustomize, only show the control if we can
         // delete the app (it was downloaded), and rename the string to "uninstall" in such a case.
@@ -182,18 +194,31 @@
         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);
-        } else {
+        } else if (useDeleteLabel) {
             setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null);
+        } else {
+            isVisible = false;
         }
         mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
 
         mActive = isVisible;
         resetHoverColor();
         ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
-        if (getText().length() > 0) {
+        if (isVisible && getText().length() > 0) {
             setText(useUninstallLabel ? R.string.delete_target_uninstall_label
                 : R.string.delete_target_label);
         }
@@ -226,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();
@@ -260,21 +288,10 @@
     }
 
     private boolean isUninstallFromWorkspace(DragObject d) {
-        if (AppsCustomizePagedView.DISABLE_ALL_APPS && isWorkspaceOrFolderApplication(d)) {
+        if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) {
             ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo;
-            if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
-                Set<String> categories = shortcut.intent.getCategories();
-                boolean includesLauncherCategory = false;
-                if (categories != null) {
-                    for (String category : categories) {
-                        if (category.equals(Intent.CATEGORY_LAUNCHER)) {
-                            includesLauncherCategory = true;
-                            break;
-                        }
-                    }
-                }
-                return includesLauncherCategory;
-            }
+            // Only allow manifest shortcuts to initiate an un-install.
+            return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent);
         }
         return false;
     }
@@ -286,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);
@@ -331,14 +347,15 @@
 
             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 Thread("deleteAppWidgetId") {
-                    public void run() {
+                new AsyncTask<Void, Void, Void>() {
+                    public Void doInBackground(Void ... args) {
                         appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+                        return null;
                     }
-                }.start();
+                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
             }
         }
         if (wasWaitingForUninstall && !mWaitingForUninstall) {
@@ -359,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 626ec42..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,14 +69,18 @@
     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;
+    boolean isLayoutRtl;
     boolean transposeLayoutWithOrientation;
 
     int desiredWorkspaceLeftRightMarginPx;
@@ -87,7 +95,8 @@
 
     int overviewModeMinIconZoneHeightPx;
     int overviewModeMaxIconZoneHeightPx;
-    int overviewModeMaxBarWidthPx;
+    int overviewModeBarItemWidthPx;
+    int overviewModeBarSpacerWidthPx;
     float overviewModeIconZoneRatio;
     float overviewModeScaleFactor;
 
@@ -117,13 +126,19 @@
     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 (!AppsCustomizePagedView.DISABLE_ALL_APPS && hs % 2 == 0) {
+        if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
             throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
         }
 
@@ -136,6 +151,11 @@
         iconTextSize = its;
         numHotseatIcons = hs;
         hotseatIconSize = his;
+        defaultLayoutId = dlId;
+        defaultNoAllAppsLayoutId = dnalId;
+    }
+
+    DeviceProfile() {
     }
 
     DeviceProfile(Context context,
@@ -167,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 =
@@ -216,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) {
@@ -281,11 +349,12 @@
 
         // Check to see if the icons fit in the new available height.  If not, then we need to
         // shrink the icon size.
-        Rect workspacePadding = getWorkspacePadding();
         float scale = 1f;
         int drawablePadding = iconDrawablePaddingOriginalPx;
         updateIconSize(1f, drawablePadding, resources, dm);
         float usedHeight = (cellHeightPx * numRows);
+
+        Rect workspacePadding = getWorkspacePadding();
         int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
         if (usedHeight > maxHeight) {
             scale = maxHeight / usedHeight;
@@ -310,7 +379,7 @@
         searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width);
         searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
         searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
-        searchBarSpaceHeightPx = searchBarHeightPx + 2 * edgeMarginPx;
+        searchBarSpaceHeightPx = searchBarHeightPx + getSearchBarTopOffset();
 
         // Calculate the actual text height
         Paint textPaint = new Paint();
@@ -318,6 +387,8 @@
         FontMetrics fm = textPaint.getFontMetrics();
         cellWidthPx = iconSizePx;
         cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top);
+        final float scaleDps = resources.getDimensionPixelSize(R.dimen.dragViewScale);
+        dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
 
         // Hotseat
         hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
@@ -346,20 +417,30 @@
         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,
                                  int awPx, int ahPx) {
-        isLandscape = (resources.getConfiguration().orientation ==
-                Configuration.ORIENTATION_LANDSCAPE);
+        Configuration configuration = resources.getConfiguration();
+        isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
         isTablet = resources.getBoolean(R.bool.is_tablet);
         isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
+        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;
@@ -382,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;
@@ -390,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);
@@ -419,6 +518,15 @@
         return sum;
     }
 
+    /** Returns the search bar top offset */
+    int getSearchBarTopOffset() {
+        if (isTablet() && !isVerticalBarLayout()) {
+            return 4 * edgeMarginPx;
+        } else {
+            return 2 * edgeMarginPx;
+        }
+    }
+
     /** Returns the search bar bounds in the current orientation */
     Rect getSearchBarBounds() {
         return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
@@ -428,7 +536,13 @@
         Rect bounds = new Rect();
         if (orientation == CellLayout.LANDSCAPE &&
                 transposeLayoutWithOrientation) {
-            bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx, availableHeightPx - edgeMarginPx);
+            if (isLayoutRtl) {
+                bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx,
+                        availableWidthPx, availableHeightPx - edgeMarginPx);
+            } else {
+                bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx,
+                        availableHeightPx - edgeMarginPx);
+            }
         } else {
             if (isTablet()) {
                 // Pad the left and right of the workspace to ensure consistent spacing
@@ -440,10 +554,12 @@
                 //      that into account here too.
                 int gap = (int) ((width - 2 * edgeMarginPx -
                         (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
-                bounds.set(edgeMarginPx + gap, 0, availableWidthPx - (edgeMarginPx + gap),
+                bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(),
+                        availableWidthPx - (edgeMarginPx + gap),
                         searchBarSpaceHeightPx);
             } else {
-                bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, 0,
+                bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
+                        getSearchBarTopOffset(),
                         availableWidthPx - (desiredWorkspaceLeftRightMarginPx -
                         defaultWidgetPadding.right), searchBarSpaceHeightPx);
             }
@@ -451,6 +567,27 @@
         return bounds;
     }
 
+    /** Returns the bounds of the workspace page indicators. */
+    Rect getWorkspacePageIndicatorBounds(Rect insets) {
+        Rect workspacePadding = getWorkspacePadding();
+        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 */
     Rect getWorkspacePadding() {
         return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
@@ -461,23 +598,32 @@
         if (orientation == CellLayout.LANDSCAPE &&
                 transposeLayoutWithOrientation) {
             // Pad the left and right of the workspace with search/hotseat bar sizes
-            padding.set(searchBarBounds.right, edgeMarginPx,
-                    hotseatBarHeightPx, edgeMarginPx);
+            if (isLayoutRtl) {
+                padding.set(hotseatBarHeightPx, edgeMarginPx,
+                        searchBarBounds.width(), edgeMarginPx);
+            } else {
+                padding.set(searchBarBounds.width(), edgeMarginPx,
+                        hotseatBarHeightPx, edgeMarginPx);
+            }
         } else {
             if (isTablet()) {
                 // Pad the left and right of the workspace to ensure consistent spacing
                 // between all icons
+                float gapScale = 1f + (dragViewScale - 1f) / 2f;
                 int width = (orientation == CellLayout.LANDSCAPE)
                         ? Math.max(widthPx, heightPx)
                         : Math.min(widthPx, heightPx);
-                // XXX: If the icon size changes across orientations, we will have to take
-                //      that into account here too.
-                int gap = (int) ((width - 2 * edgeMarginPx -
-                        (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
-                padding.set(edgeMarginPx + gap,
-                        searchBarBounds.bottom,
-                        edgeMarginPx + gap,
-                        hotseatBarHeightPx + pageIndicatorHeightPx);
+                int height = (orientation != CellLayout.LANDSCAPE)
+                        ? Math.max(widthPx, heightPx)
+                        : Math.min(widthPx, heightPx);
+                int paddingTop = searchBarBounds.bottom;
+                int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
+                int availableWidth = Math.max(0, width - (int) ((numColumns * cellWidthPx) +
+                        (numColumns * gapScale * cellWidthPx)));
+                int availableHeight = Math.max(0, height - paddingTop - paddingBottom
+                        - (int) (2 * numRows * cellHeightPx));
+                padding.set(availableWidth / 2, paddingTop + availableHeight / 2,
+                        availableWidth / 2, paddingBottom + availableHeight / 2);
             } else {
                 // Pad the top and bottom of the workspace with search/hotseat bar sizes
                 padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
@@ -490,15 +636,15 @@
     }
 
     int getWorkspacePageSpacing(int orientation) {
-        if (orientation == CellLayout.LANDSCAPE &&
-                transposeLayoutWithOrientation) {
+        if ((orientation == CellLayout.LANDSCAPE &&
+                transposeLayoutWithOrientation) || isLargeTablet()) {
             // In landscape mode the page spacing is set to the default.
             return defaultPageSpacingPx;
         } else {
             // 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);
         }
     }
 
@@ -552,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();
@@ -561,32 +722,28 @@
         View searchBar = launcher.getSearchBar();
         lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
         if (hasVerticalBarLayout) {
-            // Vertical search bar
+            // 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
+            // Horizontal search bar space
             lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
             lp.width = searchBarSpaceWidthPx;
             lp.height = searchBarSpaceHeightPx;
             searchBar.setPadding(
                     2 * edgeMarginPx,
-                    2 * edgeMarginPx,
+                    getSearchBarTopOffset(),
                     2 * edgeMarginPx, 0);
         }
         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) {
@@ -616,24 +773,17 @@
         lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
         if (hasVerticalBarLayout) {
             // Vertical hotseat
-            lp.gravity = Gravity.RIGHT;
+            lp.gravity = Gravity.END;
             lp.width = hotseatBarHeightPx;
             lp.height = LayoutParams.MATCH_PARENT;
             hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
         } else if (isTablet()) {
-            // Pad the hotseat with the grid gap calculated above
-            int gridGap = (int) ((widthPx - 2 * edgeMarginPx -
-                    (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
-            int gridWidth = (int) ((numColumns * cellWidthPx) +
-                    ((numColumns - 1) * gridGap));
-            int hotseatGap = (int) Math.max(0,
-                    (gridWidth - (numHotseatIcons * hotseatCellWidthPx))
-                            / (numHotseatIcons - 1));
+            // Pad the hotseat with the workspace padding calculated above
             lp.gravity = Gravity.BOTTOM;
             lp.width = LayoutParams.MATCH_PARENT;
             lp.height = hotseatBarHeightPx;
-            hotseat.setPadding(2 * edgeMarginPx + gridGap + hotseatGap, 0,
-                    2 * edgeMarginPx + gridGap + hotseatGap,
+            hotseat.setPadding(edgeMarginPx + padding.left, 0,
+                    edgeMarginPx + padding.right,
                     2 * edgeMarginPx);
         } else {
             // For phones, layout the hotseat without any bottom margin
@@ -672,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
@@ -692,24 +846,39 @@
                 paddingTB = Math.min(paddingTB, (int)((paddingLR + paddingTB) * 0.75f));
                 int maxAllAppsWidth = (allAppsNumCols * (allAppsCellWidthPx + 2 * paddingLR));
                 int gridPaddingLR = (availableWidthPx - maxAllAppsWidth) / 2;
-                if (gridPaddingLR > (allAppsCellWidthPx / 4)) {
+                // Only adjust the side paddings on landscape phones, or tablets
+                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 1bfaa23..6d0a2be 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -28,7 +28,6 @@
 import android.util.Log;
 import android.view.*;
 import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.R;
 
 import java.util.ArrayList;
 
@@ -330,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 56886a1..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,7 +204,7 @@
         }
 
         Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
-        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
+        if (currentFolder != null && intercept) {
             if (currentFolder.isEditingName()) {
                 if (!isEventOverFolderTextRegion(currentFolder, ev)) {
                     currentFolder.dismissEditingName();
@@ -224,22 +260,19 @@
                             sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
                             mHoverPointClosesFolder = true;
                             return true;
-                        } else if (isOverFolder) {
-                            mHoverPointClosesFolder = false;
-                        } else {
-                            return true;
                         }
+                        mHoverPointClosesFolder = false;
+                        break;
                     case MotionEvent.ACTION_HOVER_MOVE:
                         isOverFolder = isEventOverFolder(currentFolder, ev);
                         if (!isOverFolder && !mHoverPointClosesFolder) {
                             sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
                             mHoverPointClosesFolder = true;
                             return true;
-                        } else if (isOverFolder) {
-                            mHoverPointClosesFolder = false;
-                        } else {
+                        } else if (!isOverFolder) {
                             return true;
                         }
+                        mHoverPointClosesFolder = false;
                 }
             }
         }
@@ -546,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
@@ -764,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();
     }
 
@@ -772,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();
@@ -815,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.
      */
@@ -824,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/DragSource.java b/src/com/android/launcher3/DragSource.java
index cca9ab1..7369eea 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -30,6 +30,17 @@
      */
     boolean supportsFlingToDelete();
 
+    /**
+     * @return whether items dragged from this source supports 'App Info'
+     */
+    boolean supportsAppInfoDropTarget();
+
+    /**
+     * @return whether items dragged from this source supports 'Delete' drop target (e.g. to remove
+     * a shortcut.
+     */
+    boolean supportsDeleteDropTarget();
+
     /*
      * @return the scale of the icons over the workspace icon size
      */
diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java
index b66b55c..ea34e46 100644
--- a/src/com/android/launcher3/DragView.java
+++ b/src/com/android/launcher3/DragView.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.android.launcher3;
 
 import android.animation.ValueAnimator;
@@ -30,8 +29,6 @@
 import android.view.View;
 import android.view.animation.DecelerateInterpolator;
 
-import com.android.launcher3.R;
-
 public class DragView extends View {
     private static float sDragAlpha = 1f;
 
diff --git a/src/com/android/launcher3/DrawableStateProxyView.java b/src/com/android/launcher3/DrawableStateProxyView.java
index 0758de1..c83659a 100644
--- a/src/com/android/launcher3/DrawableStateProxyView.java
+++ b/src/com/android/launcher3/DrawableStateProxyView.java
@@ -23,8 +23,6 @@
 import android.view.View;
 import android.widget.LinearLayout;
 
-import com.android.launcher3.R;
-
 public class DrawableStateProxyView extends LinearLayout {
 
     private View mView;
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 42aa20d..94a07d7 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -56,36 +56,45 @@
         DisplayMetrics dm = resources.getDisplayMetrics();
         ArrayList<DeviceProfile> deviceProfiles =
                 new ArrayList<DeviceProfile>();
-        boolean hasAA = !AppsCustomizePagedView.DISABLE_ALL_APPS;
+        boolean hasAA = !LauncherAppState.isDisableAllApps();
         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 : 4), 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 : 4), 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 : 4), 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 : 4), 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 : 4), 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 : 4), 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,  6, 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, 8,  80, 14.4f,  9, 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 83be143..ff02bbb 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -16,22 +16,66 @@
 
 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;
         mBitmap = b;
+        setBounds(0, 0, b.getWidth(), b.getHeight());
     }
 
     @Override
@@ -43,7 +87,7 @@
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mPaint.setColorFilter(cf);
+        // No op
     }
 
     @Override
@@ -57,6 +101,7 @@
         mPaint.setAlpha(alpha);
     }
 
+    @Override
     public void setFilterBitmap(boolean filterBitmap) {
         mPaint.setFilterBitmap(filterBitmap);
         mPaint.setAntiAlias(filterBitmap);
@@ -68,12 +113,12 @@
 
     @Override
     public int getIntrinsicWidth() {
-        return getBounds().width();
+        return mBitmap.getWidth();
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return getBounds().height();
+        return mBitmap.getHeight();
     }
 
     @Override
@@ -89,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 1d234ff..1890af4 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -18,22 +18,20 @@
 
 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;
 import android.text.Selection;
 import android.text.Spannable;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -44,7 +42,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Interpolator;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
@@ -74,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;
@@ -82,17 +83,17 @@
     private int mState = STATE_NONE;
     private static final int REORDER_ANIMATION_DURATION = 230;
     private static final int REORDER_DELAY = 250;
-    private static final int ON_EXIT_CLOSE_DELAY = 800;
+    private static final int ON_EXIT_CLOSE_DELAY = 400;
     private boolean mRearrangeOnClose = false;
     private FolderIcon mFolderIcon;
     private int mMaxCountX;
     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];
@@ -115,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
@@ -149,13 +148,20 @@
 
         Resources res = getResources();
         mMaxCountX = (int) grid.numColumns;
-        mMaxCountY = (int) grid.numRows;
-        mMaxNumItems = mMaxCountX * mMaxCountY;
+        // Allow scrolling folders when DISABLE_ALL_APPS is true.
+        if (LauncherAppState.isDisableAllApps()) {
+            mMaxCountY = mMaxNumItems = Integer.MAX_VALUE;
+        } else {
+            mMaxCountY = (int) grid.numRows;
+            mMaxNumItems = mMaxCountX * mMaxCountY;
+        }
 
         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);
@@ -176,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();
 
@@ -237,11 +248,7 @@
                 return false;
             }
 
-            mLauncher.dismissFolderCling(null);
-
-            mLauncher.getWorkspace().onDragStartedWithItem(v);
             mLauncher.getWorkspace().beginDragShared(v, this);
-            mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
 
             mCurrentDragInfo = item;
             mEmptyCell[0] = item.cellX;
@@ -302,8 +309,8 @@
         return mFolderName;
     }
 
-    public Drawable getDragDrawable() {
-        return mIconDrawable;
+    public CellLayout getContent() {
+        return mContent;
     }
 
     /**
@@ -380,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++;
@@ -390,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) {
@@ -408,6 +415,15 @@
             mFolderName.setText("");
         }
         updateItemLocationsInDatabase();
+
+        // In case any children didn't come across during loading, clean up the folder accordingly
+        mFolderIcon.post(new Runnable() {
+            public void run() {
+                if (getItemCount() <= 1) {
+                    replaceFolderWithFinalItem();
+                }
+            }
+        });
     }
 
     /**
@@ -433,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,
@@ -455,19 +546,32 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mState = STATE_OPEN;
-                setLayerType(LAYER_TYPE_NONE, null);
-                Cling cling = mLauncher.showFirstRunFoldersCling();
-                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) {
@@ -534,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;
             }
         }
 
@@ -564,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) {
@@ -668,9 +767,6 @@
                 mReorderAlarm.setAlarm(REORDER_DELAY);
                 mPreviousTargetCell[0] = mTargetCell[0];
                 mPreviousTargetCell[1] = mTargetCell[1];
-                mDragMode = DRAG_MODE_REORDER;
-            } else {
-                mDragMode = DRAG_MODE_NONE;
             }
         }
     }
@@ -713,6 +809,7 @@
         mCurrentDragView = null;
         mSuppressOnAdd = false;
         mRearrangeOnClose = true;
+        mIsExternalDrag = false;
     }
 
     public void onDragExit(DragObject d) {
@@ -725,7 +822,6 @@
             mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
         }
         mReorderAlarm.cancelAlarm();
-        mDragMode = DRAG_MODE_NONE;
     }
 
     public void onDropCompleted(final View target, final DragObject d,
@@ -746,7 +842,7 @@
                 success && (!beingCalledAfterUninstall || mUninstallSuccessful);
 
         if (successfulDrop) {
-            if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
+            if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) {
                 replaceFolderWithFinalItem();
             }
         } else {
@@ -763,8 +859,6 @@
                 }
                 completeDragExit();
             }
-        } else {
-            mLauncher.getWorkspace().removeExtraEmptyScreen(true, null);
         }
 
         mDeleteFolderOnDropCompleted = false;
@@ -801,6 +895,16 @@
         return true;
     }
 
+    @Override
+    public boolean supportsAppInfoDropTarget() {
+        return false;
+    }
+
+    @Override
+    public boolean supportsDeleteDropTarget() {
+        return true;
+    }
+
     public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
         // Do nothing
     }
@@ -816,7 +920,7 @@
             View v = list.get(i);
             ItemInfo info = (ItemInfo) v.getTag();
             LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
-                        info.cellX, info.cellY);
+                    info.cellX, info.cellY);
         }
     }
 
@@ -994,7 +1098,13 @@
         int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(),
                 MeasureSpec.EXACTLY);
 
-        mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight());
+        if (LauncherAppState.isDisableAllApps()) {
+            // Don't cap the height of the content to allow scrolling.
+            mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight());
+        } else {
+            mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight());
+        }
+
         mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec);
         mFolderName.measure(contentAreaWidthSpec,
                 MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
@@ -1065,7 +1175,7 @@
             public void run() {
                 CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId);
 
-               View child = null;
+                View child = null;
                 // Move the item from the folder to the workspace, in the position of the folder
                 if (getItemCount() == 1) {
                     ShortcutInfo finalItem = mInfo.contents.get(0);
@@ -1077,7 +1187,10 @@
                 if (getItemCount() <= 1) {
                     // Remove the folder
                     LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
-                    cellLayout.removeView(mFolderIcon);
+                    if (cellLayout != null) {
+                        // b/12446428 -- sometimes the cell layout has already gone away?
+                        cellLayout.removeView(mFolderIcon);
+                    }
                     if (mFolderIcon instanceof DropTarget) {
                         mDragController.removeDropTarget((DropTarget) mFolderIcon);
                     }
@@ -1095,6 +1208,8 @@
         View finalChild = getItemAt(0);
         if (finalChild != null) {
             mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable);
+        } else {
+            onCompleteRunnable.run();
         }
         mDestroyed = true;
     }
@@ -1117,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 5e461a7..a359f11 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -33,14 +33,14 @@
 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;
-import android.widget.ImageView;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.launcher3.R;
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.FolderInfo.FolderListener;
 
@@ -71,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;
@@ -100,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();
@@ -122,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,
@@ -167,6 +178,7 @@
         icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
         folderInfo.addListener(icon);
 
+        icon.setOnFocusChangeListener(launcher.mFocusHandler);
         return icon;
     }
 
@@ -300,7 +312,7 @@
         }
     }
 
-    Folder getFolder() {
+    public Folder getFolder() {
         return mFolder;
     }
 
@@ -332,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());
 
@@ -356,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
@@ -372,6 +411,7 @@
 
     public void onDragExit() {
         mFolderRingAnimator.animateToNaturalState();
+        mOpenAlarm.cancelAlarm();
     }
 
     private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
@@ -462,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);
@@ -516,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));
 
@@ -540,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();
@@ -565,7 +614,7 @@
             computePreviewDrawingParams(mAnimParams.drawable);
         } else {
             v = (TextView) items.get(0);
-            d = v.getCompoundDrawables()[1];
+            d = getTopDrawable(v);
             computePreviewDrawingParams(d);
         }
 
@@ -574,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);
@@ -585,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);
@@ -673,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 bb5ae82..85a792f 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -16,14 +16,18 @@
 
 package com.android.launcher3;
 
-import java.util.ArrayList;
-
 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 094e188..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() {
@@ -95,7 +94,7 @@
         return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
     }
     public boolean isAllAppsButtonRank(int rank) {
-        if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+        if (LauncherAppState.isDisableAllApps()) {
             return false;
         } else {
             return rank == mAllAppsButtonRank;
@@ -142,7 +141,7 @@
     void resetLayout() {
         mContent.removeAllViewsInLayout();
 
-        if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
+        if (!LauncherAppState.isDisableAllApps()) {
             // Add the Apps button
             Context context = getContext();
 
@@ -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;
@@ -189,7 +185,7 @@
     void addAllAppsFolder(IconCache iconCache,
             ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
             Launcher launcher, Workspace workspace) {
-        if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+        if (LauncherAppState.isDisableAllApps()) {
             FolderInfo fi = new FolderInfo();
 
             fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
@@ -219,7 +215,7 @@
     }
 
     void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
-        if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+        if (LauncherAppState.isDisableAllApps()) {
             View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
             FolderIcon fi = null;
 
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 2ad43b6..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);
         }
@@ -62,10 +71,6 @@
         }
     }
 
-    private boolean isFromAllApps(DragSource source) {
-        return (source instanceof AppsCustomizePagedView);
-    }
-
     @Override
     public boolean acceptDrop(DragObject d) {
         // acceptDrop is called just before onDrop. We do the work here, rather than
@@ -79,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
@@ -93,7 +105,7 @@
         boolean isVisible = true;
 
         // Hide this button unless we are dragging something from AllApps
-        if (!isFromAllApps(source)) {
+        if (!source.supportsAppInfoDropTarget()) {
             isVisible = false;
         }
 
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index fb75161..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;
@@ -24,17 +25,22 @@
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.text.TextUtils;
 import android.util.Base64;
 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;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
-import org.json.*;
-
 public class InstallShortcutReceiver extends BroadcastReceiver {
     private static final String TAG = "InstallShortcutReceiver";
     private static final boolean DBG = false;
@@ -221,6 +227,7 @@
         if (intent == null) {
             return;
         }
+
         // This name is only used for comparisons and notifications, so fall back to activity name
         // if not supplied
         String name = ensureValidName(context, intent,
@@ -267,22 +274,36 @@
                 //final Intent data = pendingInfo.data;
                 final Intent intent = pendingInfo.launchIntent;
                 final String name = pendingInfo.name;
+
+                if (LauncherAppState.isDisableAllApps() && !isValidShortcutLaunchIntent(intent)) {
+                    if (DBG) Log.d(TAG, "Ignoring shortcut with launchIntent:" + intent);
+                    continue;
+                }
+
                 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
@@ -294,11 +315,35 @@
             // 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);
             }
         }
     }
 
+    /**
+     * Returns true if the intent is a valid launch intent for a shortcut.
+     * This is used to identify shortcuts which are different from the ones exposed by the
+     * applications' manifest file.
+     *
+     * When DISABLE_ALL_APPS is true, shortcuts exposed via the app's manifest should never be
+     * duplicated or removed(unless the app is un-installed).
+     *
+     * @param launchIntent The intent that will be launched when the shortcut is clicked.
+     */
+    static boolean isValidShortcutLaunchIntent(Intent launchIntent) {
+        if (launchIntent != null
+                && Intent.ACTION_MAIN.equals(launchIntent.getAction())
+                && launchIntent.getComponent() != null
+                && launchIntent.getCategories() != null
+                && launchIntent.getCategories().size() == 1
+                && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
+                && launchIntent.getExtras() == null
+                && TextUtils.isEmpty(launchIntent.getDataString())) {
+            return false;
+        }
+        return true;
+    }
+
     private static ShortcutInfo getShortcutInfo(Context context, Intent data,
                                                 Intent launchIntent) {
         if (launchIntent.getAction() == null) {
diff --git a/src/com/android/launcher3/InstallWidgetReceiver.java b/src/com/android/launcher3/InstallWidgetReceiver.java
index 0ef4780..74b9e3d 100644
--- a/src/com/android/launcher3/InstallWidgetReceiver.java
+++ b/src/com/android/launcher3/InstallWidgetReceiver.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3;
 
-import java.util.List;
-
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ClipData;
 import android.content.Context;
@@ -33,7 +31,7 @@
 import android.widget.ListAdapter;
 import android.widget.TextView;
 
-import com.android.launcher3.R;
+import java.util.List;
 
 
 /**
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index 8c4cefd..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.
  */
-class ItemInfo {
+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 89abd9f..42ec4fb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -17,18 +17,18 @@
 
 package com.android.launcher3;
 
-import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 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;
@@ -39,10 +39,12 @@
 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;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
@@ -50,19 +52,20 @@
 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,14 +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.accessibility.AccessibilityManager;
-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;
@@ -97,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;
@@ -106,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;
@@ -119,7 +136,7 @@
  */
 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;
 
@@ -129,14 +146,16 @@
     static final boolean DEBUG_RESUME_TIME = false;
     static final boolean DEBUG_DUMP_LOG = false;
 
+    static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run
+
     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
@@ -154,6 +173,7 @@
     // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
     static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
     static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
+    static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps";
 
     // The Intent extra that defines whether to ignore the launch animation
     static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
@@ -186,6 +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";
@@ -195,16 +222,19 @@
     public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
     public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false;
 
+    public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data";
+
     /** The different states that Launcher can be in. */
     private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
     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 SHOW_CLING_DURATION = 250;
-    private static final int DISMISS_CLING_DURATION = 200;
+    private static final int ACTIVITY_START_DELAY = 1000;
 
     private static final Object sLock = new Object();
     private static int sScreen = DEFAULT_SCREEN;
@@ -216,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();
@@ -225,11 +256,12 @@
 
     private Workspace mWorkspace;
     private View mLauncherView;
+    private View mPageIndicators;
     private DragLayer mDragLayer;
     private DragController mDragController;
     private View mWeightWatcher;
 
-    private AppWidgetManager mAppWidgetManager;
+    private AppWidgetManagerCompat mAppWidgetManager;
     private LauncherAppWidgetHost mAppWidgetHost;
 
     private ItemInfo mPendingAddInfo = new ItemInfo();
@@ -241,7 +273,7 @@
     private FolderInfo mFolderInfo;
 
     private Hotseat mHotseat;
-    private View mOverviewPanel;
+    private ViewGroup mOverviewPanel;
 
     private View mAllAppsButton;
 
@@ -249,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
@@ -269,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;
@@ -280,8 +309,6 @@
     private boolean mVisible = false;
     private boolean mHasFocus = false;
     private boolean mAttached = false;
-    private static final boolean DISABLE_CLINGS = false;
-    private static final boolean DISABLE_CUSTOM_CLINGS = true;
 
     private static LocaleConfiguration sLocaleConfiguration = null;
 
@@ -305,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;
 
@@ -337,9 +360,6 @@
 
     private BubbleTextView mWaitingForResume;
 
-    private HideFromAccessibilityHelper mHideFromAccessibilityHelper
-        = new HideFromAccessibilityHelper();
-
     private Runnable mBuildLayersRunnable = new Runnable() {
         public void run() {
             if (mWorkspace != null) {
@@ -348,8 +368,7 @@
         }
     };
 
-    private static ArrayList<PendingAddArguments> sPendingAddList
-            = new ArrayList<PendingAddArguments>();
+    private static PendingAddArguments sPendingAddItem;
 
     public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
 
@@ -360,11 +379,14 @@
         long screenId;
         int cellX;
         int cellY;
+        int appWidgetId;
     }
 
     private Stats mStats;
 
-    private static boolean isPropertyEnabled(String propertyName) {
+    FocusIndicatorView mFocusHandler;
+
+    static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);
     }
 
@@ -389,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();
@@ -410,6 +432,7 @@
         // 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);
@@ -418,7 +441,7 @@
 
         mStats = new Stats(this);
 
-        mAppWidgetManager = AppWidgetManager.getInstance(this);
+        mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
 
         mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
         mAppWidgetHost.startListening();
@@ -433,7 +456,6 @@
                     Environment.getExternalStorageDirectory() + "/launcher");
         }
 
-
         checkForLocaleChange();
         setContentView(R.layout.launcher);
 
@@ -452,14 +474,14 @@
         }
 
         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, -1);
+                mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
             } else {
                 // We only load the page synchronously if the user rotates (or triggers a
                 // configuration change) while launcher is in the foreground
-                mModel.startLoader(true, mWorkspace.getCurrentPage());
+                mModel.startLoader(true, mWorkspace.getRestorePage());
             }
         }
 
@@ -475,13 +497,16 @@
         // On large interfaces, we want the screen to auto-rotate based on the current orientation
         unlockScreenOrientation(true);
 
-        showFirstRunCling();
+        if (shouldShowIntroScreen()) {
+            showIntroScreen();
+        } else {
+            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() {
@@ -489,11 +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() {
+    protected void populateCustomContentContainer() {
     }
 
     /**
@@ -508,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();
         }
@@ -520,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);
         }
@@ -536,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);
         }
@@ -584,12 +602,12 @@
             mIconCache.flush();
 
             final LocaleConfiguration localeConfiguration = sLocaleConfiguration;
-            new Thread("WriteLocaleConfiguration") {
-                @Override
-                public void run() {
+            new AsyncTask<Void, Void, Void>() {
+                public Void doInBackground(Void ... args) {
                     writeConfiguration(Launcher.this, localeConfiguration);
+                    return null;
                 }
-            }.start();
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
         }
     }
 
@@ -653,10 +671,6 @@
         return mInflater;
     }
 
-    public DragLayer getDragLayer() {
-        return mDragLayer;
-    }
-
     boolean isDraggingEnabled() {
         // We prevent dragging when we are loading the workspace as it is possible to pick up a view
         // that is subsequently removed from the workspace in startBinding().
@@ -675,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;
+                }
             }
         }
     }
@@ -707,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() {
@@ -756,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,
@@ -773,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;
@@ -785,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;
         }
 
@@ -821,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);
@@ -910,10 +985,9 @@
         setWorkspaceBackground(mState == State.WORKSPACE);
 
         mPaused = false;
-        sPausedFromUserAction = false;
         if (mRestoring || mOnResumeNeedsLoad) {
-            mWorkspaceLoading = true;
-            mModel.startLoader(true, -1);
+            setWorkspaceLoading(true);
+            mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
             mRestoring = false;
             mOnResumeNeedsLoad = false;
         }
@@ -953,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
@@ -982,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;
@@ -1006,12 +1079,6 @@
         }
     }
 
-    protected void onFinishBindingItems() {
-        if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) {
-            addCustomContentToLeft();
-        }
-    }
-
     QSBScroller mQsbScroller = new QSBScroller() {
         int scrollY = 0;
 
@@ -1032,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 {
@@ -1063,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();
         }
@@ -1170,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;
         }
 
@@ -1205,8 +1279,11 @@
         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(
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
@@ -1222,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);
                 }
             }
         });
@@ -1239,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
@@ -1264,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);
@@ -1298,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.
@@ -1320,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.
@@ -1489,11 +1555,12 @@
             if (appWidgetId != -1) {
                 // Deleting an app widget ID is a void call but writes to disk before returning
                 // to the caller...
-                new Thread("deleteAppWidgetId") {
-                    public void run() {
+                new AsyncTask<Void, Void, Void>() {
+                    public Void doInBackground(Void ... args) {
                         mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+                        return null;
                     }
-                }.start();
+                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
             }
             showOutOfSpaceMessage(isHotseatLayout(layout));
             return;
@@ -1506,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);
@@ -1549,6 +1617,18 @@
             } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                 mUserPresent = true;
                 updateRunning();
+            } else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) {
+                mModel.resetLoadedState(false, true);
+                mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+                        LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
+            } else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) {
+                mModel.resetLoadedState(false, true);
+                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();
             }
         }
     };
@@ -1561,12 +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();
@@ -1617,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();
         }
     }
@@ -1700,6 +1824,26 @@
         Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
     }
 
+    public DragLayer getDragLayer() {
+        return mDragLayer;
+    }
+
+    public Workspace getWorkspace() {
+        return mWorkspace;
+    }
+
+    public Hotseat getHotseat() {
+        return mHotseat;
+    }
+
+    public ViewGroup getOverviewPanel() {
+        return mOverviewPanel;
+    }
+
+    public SearchDropTargetBar getSearchBar() {
+        return mSearchDropTargetBar;
+    }
+
     public LauncherAppWidgetHost getAppWidgetHost() {
         return mAppWidgetHost;
     }
@@ -1708,11 +1852,15 @@
         return mModel;
     }
 
+    protected SharedPreferences getSharedPrefs() {
+        return mSharedPrefs;
+    }
+
     public void closeSystemDialogs() {
         getWindow().closeAllPanels();
 
         // Whatever we were doing is hereby canceled.
-        mWaitingForResult = false;
+        setWaitingForResult(false);
     }
 
     @Override
@@ -1763,7 +1911,7 @@
             }
 
             // Reset the apps customize page
-            if (mAppsCustomizeTabHost != null) {
+            if (!alreadyOnHome && mAppsCustomizeTabHost != null) {
                 mAppsCustomizeTabHost.reset();
             }
 
@@ -1801,7 +1949,8 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         if (mWorkspace.getChildCount() > 0) {
-            outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getRestorePage());
+            outState.putInt(RUNTIME_STATE_CURRENT_SCREEN,
+                    mWorkspace.getCurrentPageOffsetFromCustomContent());
         }
         super.onSaveInstanceState(outState);
 
@@ -1851,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();
@@ -1876,10 +2030,11 @@
 
         mDragLayer.clearAllResizeFrames();
         ((ViewGroup) mWorkspace.getParent()).removeAllViews();
-        mWorkspace.removeAllViews();
+        mWorkspace.removeAllWorkspaceScreens();
         mWorkspace = null;
         mDragController = null;
 
+        PackageInstallerCompat.getInstance(this).onStop();
         LauncherAnimUtils.onDestroyActivity();
     }
 
@@ -1889,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);
     }
 
@@ -1916,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;
     }
 
     /**
@@ -1966,11 +2134,24 @@
         }
     }
 
+    public boolean isOnCustomContent() {
+        return mWorkspace.isOnOrMovingToCustomContent();
+    }
+
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        if (!mWorkspace.isInOverviewMode()) {
-            mWorkspace.enterOverviewMode();
+        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;
     }
@@ -1986,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;
@@ -2008,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() {
@@ -2024,7 +2226,7 @@
             };
             completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
                     appWidgetInfo);
-            mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false);
+            mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
         }
     }
 
@@ -2095,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 {
@@ -2110,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);
@@ -2118,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) {
@@ -2164,14 +2348,8 @@
         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(), WallpaperPickerActivity.class.getName());
+        return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
     }
 
     /**
@@ -2273,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.
@@ -2371,129 +2553,119 @@
      *
      * @param v The view that was clicked.
      */
-    public void onClickAllAppsButton(View v) {
-        showAllApps(true, AppsCustomizePagedView.ContentType.Applications, true);
-    }
-
-    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);
 
@@ -2528,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.
      */
@@ -2598,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();
     }
 
@@ -2615,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) {
@@ -2662,15 +3006,12 @@
     }
 
     public void closeFolder() {
-        Folder folder = mWorkspace.getOpenFolder();
+        Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
         if (folder != null) {
             if (folder.isEditingName()) {
                 folder.dismissEditingName();
             }
             closeFolder(folder);
-
-            // Dismiss the folder cling
-            dismissFolderCling(null);
         }
     }
 
@@ -2703,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);
                 }
@@ -2746,15 +3090,6 @@
         return mHotseat != null && layout != null &&
                 (layout instanceof CellLayout) && (layout == mHotseat.getLayout());
     }
-    Hotseat getHotseat() {
-        return mHotseat;
-    }
-    View getOverviewPanel() {
-        return mOverviewPanel;
-    }
-    SearchDropTargetBar getSearchBar() {
-        return mSearchDropTargetBar;
-    }
 
     /**
      * Returns the CellLayout of the specified container at the specified screen.
@@ -2771,30 +3106,16 @@
         }
     }
 
-    Workspace getWorkspace() {
-        return mWorkspace;
-    }
-
     public boolean isAllAppsVisible() {
         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;
@@ -2883,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) {
@@ -2890,97 +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);
-        if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
-            // Set the content type for the all apps space
+                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() {
@@ -2988,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);
@@ -3041,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
@@ -3099,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);
@@ -3138,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);
@@ -3190,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;
@@ -3230,7 +3811,6 @@
                 }
             }
         }, delay);
-
     }
 
     void exitSpringLoadedDragMode() {
@@ -3252,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) {
@@ -3404,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() {
@@ -3523,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) {
@@ -3569,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));
         }
@@ -3677,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
@@ -3703,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();
         }
     }
 
@@ -3759,23 +4284,25 @@
         }
 
         // 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 (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+        if (!LauncherAppState.isDisableAllApps() &&
                 addedApps != null && mAppsCustomizeContent != null) {
             mAppsCustomizeContent.addApps(addedApps);
         }
@@ -3824,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);
+                            }
                         }
                     }
 
@@ -3867,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 {
@@ -3917,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);
@@ -3940,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);
     }
@@ -3967,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) {
@@ -4022,6 +4653,11 @@
                 getDeviceProfile().isVerticalBarLayout();
     }
 
+    protected Rect getSearchBarBounds() {
+        return LauncherAppState.getInstance().getDynamicGrid().
+                getDeviceProfile().getSearchBarBounds();
+    }
+
     @Override
     public void bindSearchablesChanged() {
         boolean searchVisible = updateGlobalSearchIcon();
@@ -4037,7 +4673,7 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindAllApplications(final ArrayList<AppInfo> apps) {
-        if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+        if (LauncherAppState.isDisableAllApps()) {
             if (mIntentsOnWorkspaceFromUpgradePath != null) {
                 if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
                     getHotseat().addAllAppsFolder(mIconCache, apps,
@@ -4045,6 +4681,10 @@
                 }
                 mIntentsOnWorkspaceFromUpgradePath = null;
             }
+            if (mAppsCustomizeContent != null) {
+                mAppsCustomizeContent.onPackagesUpdated(
+                        LauncherModel.getSortedWidgetsAndShortcuts(this));
+            }
         } else {
             if (mAppsCustomizeContent != null) {
                 mAppsCustomizeContent.setApps(apps);
@@ -4070,16 +4710,58 @@
         }
 
         if (mWorkspace != null) {
-            mWorkspace.updateShortcuts(apps);
+            mWorkspace.updateShortcutsAndWidgets(apps);
         }
 
-        if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+        if (!LauncherAppState.isDisableAllApps() &&
                 mAppsCustomizeContent != null) {
             mAppsCustomizeContent.updateApps(apps);
         }
     }
 
     /**
+     * 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,
@@ -4089,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)) {
@@ -4100,17 +4782,17 @@
         }
 
         if (!packageNames.isEmpty()) {
-            mWorkspace.removeItemsByPackageName(packageNames);
+            mWorkspace.removeItemsByPackageName(packageNames, user);
         }
         if (!appInfos.isEmpty()) {
-            mWorkspace.removeItemsByApplicationInfo(appInfos);
+            mWorkspace.removeItemsByApplicationInfo(appInfos, user);
         }
 
         // Notify the drag controller
         mDragController.onAppsRemoved(packageNames, appInfos);
 
         // Update AllApps
-        if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+        if (!LauncherAppState.isDisableAllApps() &&
                 mAppsCustomizeContent != null) {
             mAppsCustomizeContent.removeApps(appInfos);
         }
@@ -4133,8 +4815,7 @@
         }
 
         // Update the widgets pane
-        if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
-                mAppsCustomizeContent != null) {
+        if (mAppsCustomizeContent != null) {
             mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts);
         }
     }
@@ -4196,215 +4877,41 @@
         }
     }
 
-    /* Cling related */
-    private boolean isClingsEnabled() {
-        if (DISABLE_CLINGS) {
+    /**
+     * Called when the SearchBar hint should be changed.
+     *
+     * @param hint the hint to be displayed in the search bar.
+     */
+    protected void onSearchBarHintChanged(String hint) {
+
+    }
+
+    protected boolean isLauncherPreinstalled() {
+        PackageManager pm = getPackageManager();
+        try {
+            ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0);
+            if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                return true;
+            } else {
+                return false;
+            }
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
             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;
-
-        // Disable clings for accessibility when explore by touch is enabled
-        final AccessibilityManager a11yManager = (AccessibilityManager) getSystemService(
-                ACCESSIBILITY_SERVICE);
-        if (a11yManager.isTouchExplorationEnabled()) {
-            return false;
-        }
-
-        // Restricted secondary users (child mode) will potentially have very few apps
-        // seeded when they start up for the first time. Clings won't work well with that
-//        boolean supportsLimitedUsers =
-//                android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
-//        Account[] accounts = AccountManager.get(this).getAccounts();
-//        if (supportsLimitedUsers && accounts.length == 0) {
-//            UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
-//            Bundle restrictions = um.getUserRestrictions();
-//            if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
-//               return false;
-//            }
-//        }
+    /**
+     * 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;
     }
 
-    private Cling initCling(int clingId, int scrimId, boolean animate,
-                            boolean dimNavBarVisibilty) {
-        Cling cling = (Cling) findViewById(clingId);
-        View scrim = null;
-        if (scrimId > 0) {
-            scrim = findViewById(R.id.cling_scrim);
-        }
-        if (cling != null) {
-            cling.init(this, scrim);
-            cling.show(animate, SHOW_CLING_DURATION);
-
-            if (dimNavBarVisibilty) {
-                cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
-                        View.SYSTEM_UI_FLAG_LOW_PROFILE);
-            }
-        }
-        return 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();
-                    // We should update the shared preferences on a background thread
-                    new Thread("dismissClingThread") {
-                        public void run() {
-                            SharedPreferences.Editor editor = mSharedPrefs.edit();
-                            editor.putBoolean(flag, true);
-                            editor.commit();
-                        }
-                    }.start();
-                    if (postAnimationCb != null) {
-                        postAnimationCb.run();
-                    }
-                }
-            };
-            if (duration <= 0) {
-                cleanUpClingCb.run();
-            } else {
-                cling.hide(duration, cleanUpClingCb);
-            }
-            mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
-
-            if (restoreNavBarVisibilty) {
-                cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
-                        ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
-            }
-        }
-    }
-
-    private void removeCling(int id) {
-        final View cling = findViewById(id);
-        if (cling != null) {
-            final ViewGroup parent = (ViewGroup) cling.getParent();
-            parent.post(new Runnable() {
-                @Override
-                public void run() {
-                    parent.removeView(cling);
-                }
-            });
-            mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
-        }
-    }
-
-    private boolean skipCustomClingIfNoAccounts() {
-        Cling cling = (Cling) findViewById(R.id.workspace_cling);
-        boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
-        if (customCling) {
-            AccountManager am = AccountManager.get(this);
-            if (am == null) return false;
-            Account[] accounts = am.getAccountsByType("com.google");
-            return accounts.length == 0;
-        }
+    protected boolean shouldClingFocusHotseatApp() {
         return false;
     }
-
-    public void updateCustomContentHintVisibility() {
-        Cling cling = (Cling) findViewById(R.id.first_run_cling);
-        String ccHintStr = getFirstRunCustomContentHint();
-
-        if (mWorkspace.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);
-            }
-        }
-    }
-
-    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);
-                }
-            }
-        }
-    }
-
-    public void showFirstRunCling() {
-        if (isClingsEnabled() &&
-                !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) &&
-                !skipCustomClingIfNoAccounts() ) {
-            // 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 (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
-                        getResources().getBoolean(R.bool.config_useCustomClings)) {
-                    // Use a custom cling
-                    View cling = 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) findViewById(R.id.first_run_cling);
-            if (cling != null) {
-                String sbHintStr = getFirstRunClingSearchBarHint();
-                String ccHintStr = 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 {
-            removeCling(R.id.first_run_cling);
-        }
-    }
-
     protected String getFirstRunClingSearchBarHint() {
         return "";
     }
@@ -4427,78 +4934,172 @@
         return "";
     }
 
-    public void showFirstRunWorkspaceCling() {
-        // Enable the clings only if they have not been dismissed before
-        if (isClingsEnabled() &&
-                !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) {
-            Cling c = initCling(R.id.workspace_cling, 0, false, true);
+    /**
+     * 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;
+    }
 
-            // Set the focused hotseat app if there is one
-            c.setFocusedHotseatApp(getFirstRunFocusedHotseatAppDrawableId(),
-                    getFirstRunFocusedHotseatAppRank(),
-                    getFirstRunFocusedHotseatAppComponentName(),
-                    getFirstRunFocusedHotseatAppBubbleTitle(),
-                    getFirstRunFocusedHotseatAppBubbleDescription());
-        } else {
-            removeCling(R.id.workspace_cling);
-        }
+    /**
+     * To be overridden by subclasses to launch any first run activity
+     */
+    protected Intent getFirstRunActivity() {
+        return null;
     }
-    public Cling showFirstRunFoldersCling() {
-        // Enable the clings only if they have not been dismissed before
-        if (isClingsEnabled() &&
-                !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) {
-            Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
-                    true, true);
-            return cling;
-        } else {
-            removeCling(R.id.folder_cling);
-            return null;
-        }
+
+    private boolean shouldRunFirstRunActivity() {
+        return !ActivityManager.isRunningInTestHarness() &&
+                !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
     }
-    protected SharedPreferences getSharedPrefs() {
-        return mSharedPrefs;
+
+    protected boolean hasRunFirstRunActivity() {
+        return mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
     }
-    public boolean isFolderClingVisible() {
-        Cling cling = (Cling) findViewById(R.id.folder_cling);
-        if (cling != null) {
-            return cling.getVisibility() == View.VISIBLE;
+
+    public boolean showFirstRunActivity() {
+        if (shouldRunFirstRunActivity() &&
+                hasFirstRunActivity()) {
+            Intent firstRunIntent = getFirstRunActivity();
+            if (firstRunIntent != null) {
+                startActivity(firstRunIntent);
+                markFirstRunActivityShown();
+                return true;
+            }
         }
         return false;
     }
-    public void dismissFirstRunCling(View v) {
-        Cling cling = (Cling) findViewById(R.id.first_run_cling);
-        Runnable cb = new Runnable() {
-            public void run() {
-                // Show the workspace cling next
-                showFirstRunWorkspaceCling();
-            }
-        };
-        dismissCling(cling, cb, Cling.FIRST_RUN_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, false);
 
-        // Fade out the search bar for the workspace cling coming up
-        mSearchDropTargetBar.hideSearchBar(true);
+    private void markFirstRunActivityShown() {
+        SharedPreferences.Editor editor = mSharedPrefs.edit();
+        editor.putBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, true);
+        editor.apply();
     }
-    public void dismissWorkspaceCling(View v) {
-        Cling cling = (Cling) findViewById(R.id.workspace_cling);
-        Runnable cb = null;
-        if (v == null) {
-            cb = new Runnable() {
-                public void run() {
-                    mWorkspace.enterOverviewMode();
-                }
-            };
+
+    /**
+     * 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);
         }
-        dismissCling(cling, cb, Cling.WORKSPACE_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, true);
-
-        // Fade in the search bar
-        mSearchDropTargetBar.showSearchBar(true);
     }
-    public void dismissFolderCling(View v) {
-        Cling cling = (Cling) findViewById(R.id.folder_cling);
-        dismissCling(cling, null, Cling.FOLDER_CLING_DISMISSED_KEY,
-                DISMISS_CLING_DURATION, true);
+
+    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() {
+        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() {
+        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) {
+        // 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(this, activityInfo, myUser, mIconCache, null);
+    }
+
+    public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
+            Bitmap 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.onExternalDragStartedWithItem(dragView);
+        mWorkspace.beginExternalDragShared(dragView, source);
+    }
+
+    @Override
+    public void onPageSwitch(View newPage, int newPageIndex) {
     }
 
     /**
@@ -4548,22 +5149,30 @@
     }
 
     public static void addDumpLog(String tag, String log, boolean debugLog) {
+        addDumpLog(tag, log, null, debugLog);
+    }
+
+    public static void addDumpLog(String tag, String log, Exception e, boolean debugLog) {
         if (debugLog) {
-            Log.d(tag, log);
+            if (e != null) {
+                Log.d(tag, log, e);
+            } else {
+                Log.d(tag, log);
+            }
         }
         if (DEBUG_DUMP_LOG) {
             sDateStamp.setTime(System.currentTimeMillis());
             synchronized (sDumpLogs) {
-                sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log);
+                sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log
+                    + (e == null ? "" : (", Exception: " + e)));
             }
         }
     }
 
     public void dumpLogsToLocalData() {
         if (DEBUG_DUMP_LOG) {
-            new Thread("DumpLogsToLocalData") {
-                @Override
-                public void run() {
+            new AsyncTask<Void, Void, Void>() {
+                public Void doInBackground(Void ... args) {
                     boolean success = false;
                     sDateStamp.setTime(sRunStart);
                     String FILENAME = sDateStamp.getMonth() + "-"
@@ -4601,8 +5210,9 @@
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
+                    return null;
                 }
-            }.start();
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
         }
     }
 }
@@ -4614,3 +5224,8 @@
     void onLauncherTransitionStep(Launcher l, float t);
     void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
 }
+
+interface DebugIntents {
+    static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE";
+    static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE";
+}
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 9a47eaa..246278f 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -17,28 +17,38 @@
 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.provider.Settings;
 import android.util.Log;
-import android.view.Display;
+
+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;
     private IconCache mIconCache;
-    private AppFilter mAppFilter;
     private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
     private boolean mIsScreenLarge;
     private float mScreenDensity;
     private int mLongPressTimeout = 300;
+    private boolean mWallpaperChangedSinceLastCheck;
 
     private static WeakReference<LauncherProvider> sLauncherProvider;
     private static Context sContext;
@@ -84,21 +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);
@@ -115,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);
@@ -146,7 +161,7 @@
         return mModel;
     }
 
-    IconCache getIconCache() {
+    public IconCache getIconCache() {
         return mIconCache;
     }
 
@@ -217,8 +232,39 @@
         return mLongPressTimeout;
     }
 
+    public void onWallpaperChanged() {
+        mWallpaperChangedSinceLastCheck = true;
+    }
+
+    public boolean hasWallpaperChangedSinceLastCheck() {
+        boolean result = mWallpaperChangedSinceLastCheck;
+        mWallpaperChangedSinceLastCheck = false;
+        return result;
+    }
+
     @Override
     public void onAvailableSizeChanged(DeviceProfile grid) {
         Utilities.setIconSize(grid.iconSizePx);
     }
+
+    public static boolean isDisableAllApps() {
+        // Returns false on non-dogfood builds.
+        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 2b5059b..c20c693 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -17,13 +17,26 @@
 package com.android.launcher3;
 
 import android.app.backup.BackupAgentHelper;
+import android.app.backup.BackupDataInput;
 import android.app.backup.BackupManager;
 import android.content.Context;
+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.
      *
@@ -38,9 +51,44 @@
         sBackupManager.dataChanged();
     }
 
+    @Override
+    public void onDestroy() {
+        // There is only one process accessing this preference file, but the restore
+        // 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();
+        getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+        super.onDestroy();
+    }
 
     @Override
     public void onCreate() {
-        addHelper(LauncherBackupHelper.LAUNCHER_PREFIX, new LauncherBackupHelper(this));
+        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 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 f85d484..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;
@@ -82,6 +85,8 @@
 
     public static final String LAUNCHER_PREFIX = "L";
 
+    public static final String LAUNCHER_PREFS_PREFIX = "LP";
+
     private static final Bitmap.CompressFormat IMAGE_FORMAT =
             android.graphics.Bitmap.CompressFormat.PNG;
 
@@ -105,6 +110,7 @@
             Favorites.SPANX,                   // 14
             Favorites.SPANY,                   // 15
             Favorites.TITLE,                   // 16
+            Favorites.PROFILE_ID,              // 17
     };
 
     private static final int ID_INDEX = 0;
@@ -124,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
@@ -133,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() {
@@ -165,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();
@@ -175,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.");
     }
@@ -201,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();
@@ -217,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);
@@ -259,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();
@@ -284,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);
@@ -294,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 {
@@ -321,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);
         }
     }
 
@@ -357,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 {
@@ -389,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);
         }
     }
 
@@ -413,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());
@@ -451,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);
                 }
 
             }
@@ -499,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);
         }
     }
 
@@ -531,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);
@@ -550,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());
@@ -572,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();
                     }
@@ -614,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 {
@@ -625,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);
         }
     }
 
@@ -746,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) {
@@ -763,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. */
@@ -780,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. */
@@ -799,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;
     }
 
@@ -841,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;
     }
 
@@ -851,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();
@@ -860,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;
@@ -913,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);
@@ -921,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));
             }
         }
     }
@@ -941,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++;
         }
@@ -961,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);
         }
     }
 
@@ -979,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);
@@ -1003,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
new file mode 100644
index 0000000..458d81f
--- /dev/null
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -0,0 +1,263 @@
+/*
+ * 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.accounts.Account;
+import android.accounts.AccountManager;
+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;
+
+class LauncherClings implements OnClickListener {
+    private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
+    private static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.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 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;
+
+    /** Ctor */
+    public LauncherClings(Launcher launcher) {
+        mLauncher = launcher;
+        mInflater = LayoutInflater.from(new
+                ContextThemeWrapper(mLauncher, android.R.style.Theme_DeviceDefault));
+    }
+
+    @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();
+        }
+    }
+
+    /**
+     * 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);
+            }
+        }
+    }
+
+    /** Returns whether the clings are enabled or should be shown */
+    private boolean areClingsEnabled() {
+        if (DISABLE_CLINGS) {
+            return false;
+        }
+
+        // disable clings when running in a test harness
+        if(ActivityManager.isRunningInTestHarness()) return false;
+
+        // Disable clings for accessibility when explore by touch is enabled
+        final AccessibilityManager a11yManager = (AccessibilityManager) mLauncher.getSystemService(
+                Launcher.ACCESSIBILITY_SERVICE);
+        if (a11yManager.isTouchExplorationEnabled()) {
+            return false;
+        }
+
+        // Restricted secondary users (child mode) will potentially have very few apps
+        // seeded when they start up for the first time. Clings won't work well with that
+        boolean supportsLimitedUsers =
+                android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
+        Account[] accounts = AccountManager.get(mLauncher).getAccounts();
+        if (supportsLimitedUsers && accounts.length == 0) {
+            UserManager um = (UserManager) mLauncher.getSystemService(Context.USER_SERVICE);
+            Bundle restrictions = um.getUserRestrictions();
+            if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
+                return false;
+            }
+        }
+        if (Settings.Secure.getInt(mLauncher.getContentResolver(), SKIP_FIRST_USE_HINTS, 0)
+                == 1) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean shouldShowFirstRunOrMigrationClings() {
+        SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
+        return areClingsEnabled() &&
+            !sharedPrefs.getBoolean(WORKSPACE_CLING_DISMISSED_KEY, false) &&
+            !sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false);
+    }
+
+    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 5a3b1b8..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;
@@ -43,10 +50,18 @@
 import android.text.TextUtils;
 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;
@@ -57,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;
@@ -66,16 +82,26 @@
  * 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;
 
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
+    private static final long INVALID_SCREEN_ID = -1L;
+
     private final boolean mAppsCanBeOnRemoveableStorage;
+    private final boolean mOldContentProviderExists;
 
     private final LauncherAppState mApp;
     private final Object mLock = new Object();
@@ -89,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 {
@@ -141,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();
@@ -165,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);
@@ -179,9 +215,27 @@
     }
 
     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
-        final Context context = app.getContext();
+        Context context = app.getContext();
 
         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
+        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;
@@ -189,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
@@ -216,6 +272,10 @@
         }
     }
 
+    boolean canMigrateFromOldLauncherDb(Launcher launcher) {
+        return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;
+    }
+
     static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,
                                  long screen) {
         LauncherAppState app = LauncherAppState.getInstance();
@@ -277,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
@@ -295,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
@@ -315,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;
                         }
 
@@ -370,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;
@@ -389,7 +523,10 @@
                                     }
                                 }
                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
-                                        addNotAnimated, addAnimated, allAppsApps);
+                                        addNotAnimated, addAnimated, null);
+                                if (!restoredAppsFinal.isEmpty()) {
+                                    callbacks.bindAppsUpdated(restoredAppsFinal);
+                                }
                             }
                         }
                     });
@@ -399,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 " +
@@ -415,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
@@ -584,8 +714,9 @@
             // as in Workspace.onDrop. Here, we just add/remove them from the list of items
             // that are on the desktop, as appropriate
             ItemInfo modelItem = sBgItemsIdMap.get(itemId);
-            if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
-                    modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            if (modelItem != null &&
+                    (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+                     modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
                 switch (modelItem.itemType) {
                     case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
@@ -730,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");
     }
@@ -741,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();
@@ -754,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.
      */
@@ -762,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);
@@ -772,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();
@@ -783,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();
@@ -857,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 :
@@ -870,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:
@@ -909,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);
                 }
             }
         };
@@ -979,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();
@@ -1041,60 +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)) {
-            // First, schedule to add these apps back in.
-            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
-            // Then, rebind everything.
-            startLoaderFromBackground();
-        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            enqueuePackageUpdated(new PackageUpdatedTask(
-                        PackageUpdatedTask.OP_UNAVAILABLE, packages));
-        } 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)) {
@@ -1120,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.
@@ -1157,7 +1368,7 @@
             }
         }
         if (runLoader) {
-            startLoader(false, -1);
+            startLoader(false, PagedView.INVALID_RESTORE_PAGE);
         }
     }
 
@@ -1175,7 +1386,15 @@
         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);
+    }
+
+    public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
         synchronized (mLock) {
             if (DEBUG_LOADERS) {
                 Log.d(TAG, "startLoader isLaunching=" + isLaunching);
@@ -1183,15 +1402,18 @@
 
             // 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) {
                 // If there is already one running, tell it to stop.
                 // also, don't downgrade isLaunching if we're already running
                 isLaunching = isLaunching || stopLoaderLocked();
-                mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching);
-                if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {
+                mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);
+                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
+                        && mAllAppsLoaded && mWorkspaceLoaded) {
                     mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                 } else {
                     sWorkerThread.setPriority(Thread.NORM_PRIORITY);
@@ -1204,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();
         }
     }
 
@@ -1280,13 +1507,15 @@
         private boolean mIsLoadingAndBindingWorkspace;
         private boolean mStopped;
         private boolean mLoadAndBindStepFinished;
+        private int mFlags;
 
         private HashMap<Object, CharSequence> mLabelCache;
 
-        LoaderTask(Context context, boolean isLaunching) {
+        LoaderTask(Context context, boolean isLaunching, int flags) {
             mContext = context;
             mIsLaunching = isLaunching;
             mLabelCache = new HashMap<Object, CharSequence>();
+            mFlags = flags;
         }
 
         boolean isLaunching() {
@@ -1359,7 +1588,7 @@
         }
 
         void runBindSynchronousPage(int synchronousBindPage) {
-            if (synchronousBindPage < 0) {
+            if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {
                 // Ensure that we have a valid page index to load synchronously
                 throw new RuntimeException("Should not call runBindSynchronousPage() without " +
                         "valid page index");
@@ -1448,7 +1677,7 @@
                 sBgDbIconCache.clear();
             }
 
-            if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+            if (LauncherAppState.isDisableAllApps()) {
                 // Ensure that all the applications that are in the system are
                 // represented on the home screen.
                 if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
@@ -1514,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);
@@ -1524,47 +1753,55 @@
                 }
             }
             if (!added.isEmpty()) {
-                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
-                addAndBindAddedApps(context, added, cb, new ArrayList<AppInfo>());
+                addAndBindAddedWorkspaceApps(context, added);
             }
         }
 
-        private boolean checkItemDimensions(ItemInfo info) {
-            LauncherAppState app = LauncherAppState.getInstance();
-            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-            return (info.cellX + info.spanX) > (int) grid.numColumns ||
-                    (info.cellY + info.spanY) > (int) grid.numRows;
-        }
-
         // check & update map of what's occupied; used to discard overlapping/invalid items
         private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,
-                                           AtomicBoolean deleteOnItemOverlap) {
+                                           AtomicBoolean deleteOnInvalidPlacement) {
             LauncherAppState app = LauncherAppState.getInstance();
             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-            int countX = (int) grid.numColumns;
-            int countY = (int) grid.numRows;
+            final int countX = (int) grid.numColumns;
+            final int countY = (int) grid.numRows;
 
             long containerIndex = item.screenId;
             if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                 // Return early if we detect that an item is under the hotseat button
                 if (mCallbacks == null ||
                         mCallbacks.get().isAllAppsButtonRank((int) item.screenId)) {
-                    deleteOnItemOverlap.set(true);
+                    deleteOnInvalidPlacement.set(true);
+                    Log.e(TAG, "Error loading shortcut into hotseat " + item
+                            + " into position (" + item.screenId + ":" + item.cellX + ","
+                            + item.cellY + ") occupied by all apps");
                     return false;
                 }
 
-                if (occupied.containsKey(LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
-                    if (occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
-                            [(int) item.screenId][0] != null) {
+                final ItemInfo[][] hotseatItems =
+                        occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
+
+                if (item.screenId >= grid.numHotseatIcons) {
+                    Log.e(TAG, "Error loading shortcut " + item
+                            + " into hotseat position " + item.screenId
+                            + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)
+                            + ")");
+                    return false;
+                }
+
+                if (hotseatItems != null) {
+                    if (hotseatItems[(int) item.screenId][0] != null) {
                         Log.e(TAG, "Error loading shortcut into hotseat " + item
                                 + " into position (" + item.screenId + ":" + item.cellX + ","
                                 + item.cellY + ") occupied by "
                                 + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
                                 [(int) item.screenId][0]);
                             return false;
+                    } else {
+                        hotseatItems[(int) item.screenId][0] = item;
+                        return true;
                     }
                 } else {
-                    ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];
+                    final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];
                     items[(int) item.screenId][0] = item;
                     occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
                     return true;
@@ -1579,7 +1816,17 @@
                 occupied.put(item.screenId, items);
             }
 
-            ItemInfo[][] screens = occupied.get(item.screenId);
+            final ItemInfo[][] screens = occupied.get(item.screenId);
+            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                    item.cellX < 0 || item.cellY < 0 ||
+                    item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
+                Log.e(TAG, "Error loading shortcut " + item
+                        + " into cell (" + containerIndex + "-" + item.screenId + ":"
+                        + item.cellX + "," + item.cellY
+                        + ") out of screen bounds ( " + countX + "x" + countY + ")");
+                return false;
+            }
+
             // Check if any workspace icons overlap with each other
             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
@@ -1614,7 +1861,7 @@
             }
         }
 
-        /** Returns whether this is an upgradge path */
+        /** Returns whether this is an upgrade path */
         private boolean loadWorkspace() {
             // Log to disk
             Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);
@@ -1626,25 +1873,44 @@
             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();
             int countX = (int) grid.numColumns;
             int countY = (int) grid.numRows;
 
-            // Make sure the default workspace is loaded, if needed
-            LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+            if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
+                Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
+                LauncherAppState.getLauncherProvider().deleteDatabase();
+            }
 
-            // Check if we need to do any upgrade-path logic
-            boolean loadedOldDb = LauncherAppState.getLauncherProvider().justLoadedOldDb();
+            if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {
+                // append the user's Launcher2 shortcuts
+                Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);
+                LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();
+            } else {
+                // Make sure the default workspace is loaded
+                Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
+                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
+            }
+
+            // 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);
 
@@ -1684,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);
@@ -1694,41 +1964,144 @@
                     int container;
                     long id;
                     Intent intent;
+                    UserHandleCompat user;
 
                     while (!mStopped && c.moveToNext()) {
-                        AtomicBoolean deleteOnItemOverlap = new AtomicBoolean(false);
+                        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,
@@ -1757,18 +2130,14 @@
                                     info.cellY = c.getInt(cellYIndex);
                                     info.spanX = 1;
                                     info.spanY = 1;
-                                    // Skip loading items that are out of bounds
-                                    if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                                        if (checkItemDimensions(info)) {
-                                            Launcher.addDumpLog(TAG, "Skipped loading out of bounds shortcut: "
-                                                    + info + ", " + grid.numColumns + "x" + grid.numRows, true);
-                                            continue;
-                                        }
-                                    }
+                                    info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
+                                    info.isDisabled = isSafeMode
+                                            && !Utilities.isSystemApp(context, intent);
+
                                     // check & update map of what's occupied
-                                    deleteOnItemOverlap.set(false);
-                                    if (!checkItemPlacement(occupied, info, deleteOnItemOverlap)) {
-                                        if (deleteOnItemOverlap.get()) {
+                                    deleteOnInvalidPlacement.set(false);
+                                    if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) {
+                                        if (deleteOnInvalidPlacement.get()) {
                                             itemsToRemove.add(id);
                                         }
                                         break;
@@ -1810,18 +2179,11 @@
                                 folderInfo.spanX = 1;
                                 folderInfo.spanY = 1;
 
-                                // Skip loading items that are out of bounds
-                                if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                                    if (checkItemDimensions(folderInfo)) {
-                                        Log.d(TAG, "Skipped loading out of bounds folder");
-                                        continue;
-                                    }
-                                }
                                 // check & update map of what's occupied
-                                deleteOnItemOverlap.set(false);
+                                deleteOnInvalidPlacement.set(false);
                                 if (!checkItemPlacement(occupied, folderInfo,
-                                        deleteOnItemOverlap)) {
-                                    if (deleteOnItemOverlap.get()) {
+                                        deleteOnInvalidPlacement)) {
+                                    if (deleteOnInvalidPlacement.get()) {
                                         itemsToRemove.add(id);
                                     }
                                     break;
@@ -1834,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;
@@ -1842,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 &&
@@ -1877,29 +2292,26 @@
                                     }
 
                                     appWidgetInfo.container = c.getInt(containerIndex);
-                                    // Skip loading items that are out of bounds
-                                    if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                                        if (checkItemDimensions(appWidgetInfo)) {
-                                            Log.d(TAG, "Skipped loading out of bounds app widget");
-                                            continue;
-                                        }
-                                    }
                                     // check & update map of what's occupied
-                                    deleteOnItemOverlap.set(false);
+                                    deleteOnInvalidPlacement.set(false);
                                     if (!checkItemPlacement(occupied, appWidgetInfo,
-                                            deleteOnItemOverlap)) {
-                                        if (deleteOnItemOverlap.get()) {
+                                            deleteOnInvalidPlacement)) {
+                                        if (deleteOnInvalidPlacement.get()) {
                                             itemsToRemove.add(id);
                                         }
                                         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);
@@ -1908,7 +2320,7 @@
                                 break;
                             }
                         } catch (Exception e) {
-                            Launcher.addDumpLog(TAG, "Desktop items loading interrupted: " + e, true);
+                            Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);
                         }
                     }
                 } finally {
@@ -1925,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) {
@@ -1941,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.
@@ -2014,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 + " ]");
@@ -2026,7 +2468,7 @@
 
         /** Filters the set of items who are directly or indirectly (via another container) on the
          * specified screen. */
-        private void filterCurrentWorkspaceItems(int currentScreen,
+        private void filterCurrentWorkspaceItems(long currentScreenId,
                 ArrayList<ItemInfo> allWorkspaceItems,
                 ArrayList<ItemInfo> currentScreenItems,
                 ArrayList<ItemInfo> otherScreenItems) {
@@ -2039,12 +2481,6 @@
                 }
             }
 
-            // If we aren't filtering on a screen, then the set of items to load is the full set of
-            // items given.
-            if (currentScreen < 0) {
-                currentScreenItems.addAll(allWorkspaceItems);
-            }
-
             // Order the set of items by their containers first, this allows use to walk through the
             // list sequentially, build up a list of containers that are in the specified screen,
             // as well as all items in those containers.
@@ -2057,7 +2493,7 @@
             });
             for (ItemInfo info : allWorkspaceItems) {
                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                    if (info.screenId == currentScreen) {
+                    if (info.screenId == currentScreenId) {
                         currentScreenItems.add(info);
                         itemsOnScreen.add(info.id);
                     } else {
@@ -2078,20 +2514,15 @@
         }
 
         /** Filters the set of widgets which are on the specified screen. */
-        private void filterCurrentAppWidgets(int currentScreen,
+        private void filterCurrentAppWidgets(long currentScreenId,
                 ArrayList<LauncherAppWidgetInfo> appWidgets,
                 ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,
                 ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {
-            // If we aren't filtering on a screen, then the set of items to load is the full set of
-            // widgets given.
-            if (currentScreen < 0) {
-                currentScreenWidgets.addAll(appWidgets);
-            }
 
             for (LauncherAppWidgetInfo widget : appWidgets) {
                 if (widget == null) continue;
                 if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
-                        widget.screenId == currentScreen) {
+                        widget.screenId == currentScreenId) {
                     currentScreenWidgets.add(widget);
                 } else {
                     otherScreenWidgets.add(widget);
@@ -2100,23 +2531,18 @@
         }
 
         /** Filters the set of folders which are on the specified screen. */
-        private void filterCurrentFolders(int currentScreen,
+        private void filterCurrentFolders(long currentScreenId,
                 HashMap<Long, ItemInfo> itemsIdMap,
                 HashMap<Long, FolderInfo> folders,
                 HashMap<Long, FolderInfo> currentScreenFolders,
                 HashMap<Long, FolderInfo> otherScreenFolders) {
-            // If we aren't filtering on a screen, then the set of items to load is the full set of
-            // widgets given.
-            if (currentScreen < 0) {
-                currentScreenFolders.putAll(folders);
-            }
 
             for (long id : folders.keySet()) {
                 ItemInfo info = itemsIdMap.get(id);
                 FolderInfo folder = folders.get(id);
                 if (info == null || folder == null) continue;
                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
-                        info.screenId == currentScreen) {
+                        info.screenId == currentScreenId) {
                     currentScreenFolders.put(id, folder);
                 } else {
                     otherScreenFolders.put(id, folder);
@@ -2184,7 +2610,9 @@
                     }
                 };
                 if (postOnMainThread) {
-                    deferredBindRunnables.add(r);
+                    synchronized (deferredBindRunnables) {
+                        deferredBindRunnables.add(r);
+                    }
                 } else {
                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                 }
@@ -2201,7 +2629,9 @@
                     }
                 };
                 if (postOnMainThread) {
-                    deferredBindRunnables.add(r);
+                    synchronized (deferredBindRunnables) {
+                        deferredBindRunnables.add(r);
+                    }
                 } else {
                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
                 }
@@ -2243,13 +2673,7 @@
                 return;
             }
 
-            final boolean isLoadingSynchronously = (synchronizeBindPage > -1);
-            final int currentScreen = isLoadingSynchronously ? synchronizeBindPage :
-                oldCallbacks.getCurrentWorkspaceScreen();
-
-            // Load all the items that are on the current page first (and in the process, unbind
-            // all the existing workspace items before we call startBinding() below.
-            unbindWorkspaceItemsOnMainThread();
+            // Save a copy of all the bg-thread collections
             ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
             ArrayList<LauncherAppWidgetInfo> appWidgets =
                     new ArrayList<LauncherAppWidgetInfo>();
@@ -2264,6 +2688,23 @@
                 orderedScreenIds.addAll(sBgWorkspaceScreens);
             }
 
+            final boolean isLoadingSynchronously =
+                    synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;
+            int currScreen = isLoadingSynchronously ? synchronizeBindPage :
+                oldCallbacks.getCurrentWorkspaceScreen();
+            if (currScreen >= orderedScreenIds.size()) {
+                // There may be no workspace screens (just hotseat items and an empty page).
+                currScreen = PagedView.INVALID_RESTORE_PAGE;
+            }
+            final int currentScreen = currScreen;
+            final long currentScreenId = currentScreen < 0
+                    ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);
+
+            // Load all the items that are on the current page first (and in the process, unbind
+            // all the existing workspace items before we call startBinding() below.
+            unbindWorkspaceItemsOnMainThread();
+
+            // Separate the items that are on the current screen, and all the other remaining items
             ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
             ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();
             ArrayList<LauncherAppWidgetInfo> currentAppWidgets =
@@ -2273,12 +2714,11 @@
             HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();
             HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();
 
-            // Separate the items that are on the current screen, and all the other remaining items
-            filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems,
+            filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
                     otherWorkspaceItems);
-            filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets,
+            filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
                     otherAppWidgets);
-            filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders,
+            filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,
                     otherFolders);
             sortWorkspaceItemsSpatially(currentWorkspaceItems);
             sortWorkspaceItemsSpatially(otherWorkspaceItems);
@@ -2303,7 +2743,7 @@
                 r = new Runnable() {
                     public void run() {
                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);
-                        if (callbacks != null) {
+                        if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {
                             callbacks.onPageBoundSynchronously(currentScreen);
                         }
                     }
@@ -2313,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));
 
@@ -2335,7 +2777,9 @@
                 }
             };
             if (isLoadingSynchronously) {
-                mDeferredBindRunnables.add(r);
+                synchronized (mDeferredBindRunnables) {
+                    mDeferredBindRunnables.add(r);
+                }
             } else {
                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
             }
@@ -2401,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>();
@@ -2479,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;
@@ -2490,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() {
@@ -2504,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]);
                     }
@@ -2519,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]);
                     }
@@ -2551,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 (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
-                    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);
                         }
                     }
@@ -2594,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
@@ -2624,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() {
@@ -2658,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);
     }
 
     /**
@@ -2705,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) {
@@ -2761,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
@@ -2789,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;
     }
 
@@ -2798,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);
                     }
@@ -2821,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);
@@ -2853,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;
     }
@@ -2866,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.
@@ -2896,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 {
@@ -2911,7 +3478,7 @@
             }
             break;
         default:
-            icon = getFallbackIcon();
+            icon = mIconCache.getDefaultIcon(info.user);
             info.usingFallbackIcon = true;
             info.customIcon = false;
             break;
@@ -2950,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();
@@ -2962,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);
@@ -3028,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);
                 }
@@ -3037,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;
@@ -3113,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;
             }
         };
     }
@@ -3130,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);
@@ -3145,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);
             }
@@ -3181,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();
         }
@@ -3194,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 b5db338..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,19 +49,24 @@
 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;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 
 public class LauncherProvider extends ContentProvider {
@@ -66,11 +75,14 @@
 
     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;
 
+    // Should we attempt to load anything from the com.android.launcher2 provider?
+    static final boolean IMPORT_LAUNCHER2_DATABASE = false;
+
     static final String TABLE_FAVORITES = "favorites";
     static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
     static final String PARAMETER_NOTIFY = "notify";
@@ -78,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.
@@ -103,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);
@@ -130,9 +152,13 @@
 
     private static long dbInsertAndCheck(DatabaseHelper helper,
             SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
-        if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+        if (values == null) {
+            throw new RuntimeException("Error: attempting to insert null values");
+        }
+        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);
     }
 
@@ -146,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);
@@ -157,6 +191,7 @@
         return uri;
     }
 
+
     @Override
     public int bulkInsert(Uri uri, ContentValues[] values) {
         SqlArguments args = new SqlArguments(uri);
@@ -181,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);
 
@@ -211,6 +260,9 @@
 
         // always notify the backup agent
         LauncherBackupAgentHelper.dataChanged(getContext());
+        if (mListener != null) {
+            mListener.onLauncherProviderChange();
+        }
     }
 
     private void addModifiedTime(ContentValues values) {
@@ -256,56 +308,132 @@
     }
 
     /**
-     * @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, R.xml.default_workspace);
+            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(),
+                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 grid.defaultNoAllAppsLayoutId;
+        } else {
+            return grid.defaultLayoutId;
+        }
+    }
+
     private static interface ContentValuesCallback {
         public void onRow(ContentValues values);
     }
 
-    private static class DatabaseHelper extends SQLiteOpenHelper {
+    private static boolean shouldImportLauncher2Database(Context context) {
+        boolean isTablet = context.getResources().getBoolean(R.bool.is_tablet);
+
+        // We don't import the old databse for tablets, as the grid size has changed.
+        return !isTablet && IMPORT_LAUNCHER2_DATABASE;
+    }
+
+    public void deleteDatabase() {
+        // Are you sure? (y/n)
+        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final File dbFile = new File(db.getPath());
+        mOpenHelper.close();
+        if (dbFile.exists()) {
+            SQLiteDatabase.deleteDatabase(dbFile);
+        }
+        mOpenHelper = new DatabaseHelper(getContext());
+    }
+
+    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
@@ -318,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
@@ -335,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," +
@@ -356,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);
 
@@ -366,32 +505,38 @@
                 sendAppWidgetResetNotify();
             }
 
-            // Try converting the old database
-            ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
-                public void onRow(ContentValues values) {
-                    int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
-                    if (container == Favorites.CONTAINER_DESKTOP) {
-                        int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
-                        screen = (int) upgradeLauncherDb_permuteScreens(screen);
-                        values.put(LauncherSettings.Favorites.SCREEN, screen);
+            if (shouldImportLauncher2Database(mContext)) {
+                // Try converting the old database
+                ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
+                    public void onRow(ContentValues values) {
+                        int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
+                        if (container == Favorites.CONTAINER_DESKTOP) {
+                            int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
+                            screen = (int) upgradeLauncherDb_permuteScreens(screen);
+                            values.put(LauncherSettings.Favorites.SCREEN, screen);
+                        }
+                    }
+                };
+                Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
+                        "/old_favorites?notify=true");
+                if (!convertDatabase(db, uri, permuteScreensCb, true)) {
+                    // Try and upgrade from the Launcher2 db
+                    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();
+                        return;
                     }
                 }
-            };
-            Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
-                    "/old_favorites?notify=true");
-            if (!convertDatabase(db, uri, permuteScreensCb, true)) {
-                // Try and upgrade from the Launcher2 db
-                uri = LauncherSettings.Favorites.OLD_CONTENT_URI;
-                if (!convertDatabase(db, uri, permuteScreensCb, false)) {
-                    // If we fail, then set a flag to load the default workspace
-                    setFlagEmptyDbCreated();
-                    return;
-                }
+                // Right now, in non-default workspace cases, we want to run the final
+                // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
+                // set that flag too.
+                setFlagJustLoadedOldDb();
+            } else {
+                // Fresh and clean launcher DB.
+                mMaxItemId = initializeMaxItemId(db);
+                setFlagEmptyDbCreated();
             }
-            // Right now, in non-default workspace cases, we want to run the final
-            // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
-            // set that flag too.
-            setFlagJustLoadedOldDb();
         }
 
         private void addWorkspacesTable(SQLiteDatabase db) {
@@ -402,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);
@@ -613,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;
             }
 
@@ -657,7 +834,6 @@
                 }
             }
 
-
             if (version < 15) {
                 db.beginTransaction();
                 try {
@@ -676,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);
@@ -685,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 });
@@ -826,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");
@@ -834,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);
 
@@ -989,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;
@@ -1007,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();
@@ -1041,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);
@@ -1081,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>"),
@@ -1092,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);
@@ -1176,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) {
@@ -1261,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;
@@ -1286,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();
@@ -1311,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 {
@@ -1323,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);
 
@@ -1340,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());
@@ -1367,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);
@@ -1392,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) {
@@ -1406,13 +1950,296 @@
             }
             return id;
         }
+
+        private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
+            final ContentResolver resolver = mContext.getContentResolver();
+            Cursor c = null;
+            int count = 0;
+            int curScreen = 0;
+
+            try {
+                c = resolver.query(uri, null, null, null, "title ASC");
+            } catch (Exception e) {
+                // Ignore
+            }
+
+            // We already have a favorites database in the old provider
+            if (c != null) {
+                try {
+                    if (c.getCount() > 0) {
+                        final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+                        final int intentIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+                        final int titleIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+                        final int iconTypeIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+                        final int iconIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+                        final int iconPackageIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+                        final int iconResourceIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+                        final int containerIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+                        final int itemTypeIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+                        final int screenIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+                        final int cellXIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+                        final int cellYIndex
+                                = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+                        final int uriIndex
+                                = 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;
+                        int curY = 0;
+
+                        final LauncherAppState app = LauncherAppState.getInstance();
+                        final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+                        final int width = (int) grid.numColumns;
+                        final int height = (int) grid.numRows;
+                        final int hotseatWidth = (int) grid.numHotseatIcons;
+
+                        final HashSet<String> seenIntents = new HashSet<String>(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);
+                            if (itemType != Favorites.ITEM_TYPE_APPLICATION
+                                    && itemType != Favorites.ITEM_TYPE_SHORTCUT
+                                    && itemType != Favorites.ITEM_TYPE_FOLDER) {
+                                continue;
+                            }
+
+                            final int cellX = c.getInt(cellXIndex);
+                            final int cellY = c.getInt(cellYIndex);
+                            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) + "\" ("
+                                + 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 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);
+                                    }
+                                }
+                            }
+
+                            ContentValues values = new ContentValues(c.getColumnCount());
+                            values.put(LauncherSettings.Favorites._ID, c.getInt(idIndex));
+                            values.put(LauncherSettings.Favorites.INTENT, intentStr);
+                            values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
+                            values.put(LauncherSettings.Favorites.ICON_TYPE,
+                                    c.getInt(iconTypeIndex));
+                            values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
+                            values.put(LauncherSettings.Favorites.ICON_PACKAGE,
+                                    c.getString(iconPackageIndex));
+                            values.put(LauncherSettings.Favorites.ICON_RESOURCE,
+                                    c.getString(iconResourceIndex));
+                            values.put(LauncherSettings.Favorites.ITEM_TYPE, itemType);
+                            values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1);
+                            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) {
+                                hotseat.put(screen, values);
+                            }
+
+                            if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                // In a folder or in the hotseat, preserve position
+                                values.put(LauncherSettings.Favorites.SCREEN, screen);
+                                values.put(LauncherSettings.Favorites.CELLX, cellX);
+                                values.put(LauncherSettings.Favorites.CELLY, cellY);
+                            } else {
+                                // 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);
+
+                            if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+                                shortcuts.add(values);
+                            } else {
+                                folders.add(values);
+                            }
+                        }
+
+                        // 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 {
+                                for (ContentValues row: allItems) {
+                                    if (row == null) continue;
+                                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, row)
+                                            < 0) {
+                                        return;
+                                    } else {
+                                        count++;
+                                    }
+                                }
+                                db.setTransactionSuccessful();
+                            } finally {
+                                db.endTransaction();
+                            }
+                        }
+
+                        db.beginTransaction();
+                        try {
+                            for (i=0; i<=curScreen; i++) {
+                                final ContentValues values = new ContentValues();
+                                values.put(LauncherSettings.WorkspaceScreens._ID, i);
+                                values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+                                if (dbInsertAndCheck(this, db, TABLE_WORKSPACE_SCREENS, null, values)
+                                        < 0) {
+                                    return;
+                                }
+                            }
+                            db.setTransactionSuccessful();
+                        } finally {
+                            db.endTransaction();
+                        }
+                    }
+                } finally {
+                    c.close();
+                }
+            }
+
+            Launcher.addDumpLog(TAG, "migrated " + count + " icons from Launcher2 into "
+                    + (curScreen+1) + " screens", true);
+
+            // ensure that new screens are created to hold these icons
+            setFlagJustLoadedOldDb();
+
+            // Update max IDs; very important since we just grabbed IDs from another database
+            mMaxItemId = initializeMaxItemId(db);
+            mMaxScreenId = initializeMaxScreenId(db);
+            if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId + " mMaxScreenId: " + mMaxScreenId);
+        }
     }
 
     /**
      * 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]);
@@ -1423,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;
@@ -1454,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/LauncherWallpaperPickerActivity.java b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
new file mode 100644
index 0000000..10fe013
--- /dev/null
+++ b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher3;
+
+import android.content.Intent;
+
+public class LauncherWallpaperPickerActivity extends WallpaperPickerActivity {
+    @Override
+    public void startActivityForResultSafely(Intent intent, int requestCode) {
+        Utilities.startActivityForResultSafely(this, intent, requestCode);
+    }
+    @Override
+    public boolean enableRotation() {
+        return Utilities.isRotationEnabled(this);
+    }
+}
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/OnAlarmListener.java b/src/com/android/launcher3/OnAlarmListener.java
new file mode 100644
index 0000000..b5ef83e
--- /dev/null
+++ b/src/com/android/launcher3/OnAlarmListener.java
@@ -0,0 +1,5 @@
+package com.android.launcher3;
+
+public interface OnAlarmListener {
+    public void onAlarm(Alarm alarm);
+}
diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java
index 08e5f72..62ea03b 100644
--- a/src/com/android/launcher3/PageIndicator.java
+++ b/src/com/android/launcher3/PageIndicator.java
@@ -16,22 +16,12 @@
 
 package com.android.launcher3;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.LayoutTransition;
-import android.animation.TimeInterpolator;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.LinearLayout;
-import com.android.launcher3.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java
index b1025d6..f012db7 100644
--- a/src/com/android/launcher3/PageIndicatorMarker.java
+++ b/src/com/android/launcher3/PageIndicatorMarker.java
@@ -16,17 +16,11 @@
 
 package com.android.launcher3;
 
-import android.animation.AnimatorListenerAdapter;
-import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
 import android.widget.FrameLayout;
-import com.android.launcher3.R;
+import android.widget.ImageView;
 
 public class PageIndicatorMarker extends FrameLayout {
     @SuppressWarnings("unused")
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index c854498..48fc0c9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -32,7 +32,6 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -51,7 +50,6 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
-import android.widget.Scroller;
 
 import java.util.ArrayList;
 
@@ -76,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.
@@ -153,18 +152,12 @@
 
     protected int mTouchState = TOUCH_STATE_REST;
     protected boolean mForceScreenScrolled = false;
-    private boolean mScrollAbortedFromIntercept = 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;
@@ -174,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
@@ -286,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(
@@ -342,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 =
@@ -452,6 +439,10 @@
         return new PageIndicator.PageMarkerResources();
     }
 
+    /**
+     * Add a page change listener which will be called when a page is _finished_ listening.
+     *
+     */
     public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
         mPageSwitchListener = pageSwitchListener;
         if (mPageSwitchListener != null) {
@@ -526,6 +517,7 @@
      */
     void stopScrolling() {
         mCurrentPage = getNextPage();
+        notifyPageSwitchListener();
         forceFinishScroller();
     }
 
@@ -545,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.
      */
@@ -558,7 +563,7 @@
             return;
         }
         mForceScreenScrolled = true;
-        mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        mCurrentPage = validateNewPage(currentPage);
         updateCurrentPageScroll();
         notifyPageSwitchListener();
         invalidate();
@@ -571,15 +576,29 @@
     void setRestorePage(int restorePage) {
         mRestorePage = restorePage;
     }
+    int getRestorePage() {
+        return mRestorePage;
+    }
 
+    /**
+     * Should be called whenever the page changes. In the case of a scroll, we wait until the page
+     * has settled.
+     */
     protected void notifyPageSwitchListener() {
         if (mPageSwitchListener != null) {
-            mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
+            mPageSwitchListener.onPageSwitch(getPageAt(getNextPage()), getNextPage());
         }
 
+        updatePageIndicator();
+    }
+
+    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() {
@@ -714,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();
 
@@ -830,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);
@@ -874,6 +894,9 @@
                     childWidth = getViewportWidth() - mInsets.left - mInsets.right;
                     childHeight = getViewportHeight();
                 }
+                if (referenceChildWidth == 0) {
+                    referenceChildWidth = childWidth;
+                }
 
                 final int childWidthMeasureSpec =
                         MeasureSpec.makeMeasureSpec(childWidth, childWidthMode);
@@ -882,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) {
@@ -961,9 +999,7 @@
         }
 
         if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
-            setHorizontalScrollBarEnabled(false);
             updateCurrentPageScroll();
-            setHorizontalScrollBarEnabled(true);
             mFirstLayout = false;
         }
 
@@ -1092,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);
     }
@@ -1145,27 +1181,27 @@
     }
 
     protected boolean shouldDrawChild(View child) {
-        return child.getAlpha() > 0 && child.getVisibility() == VISIBLE;
+        return child.getVisibility() == VISIBLE;
     }
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        int halfScreenSize = getViewportWidth() / 2;
-        // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
-        // Otherwise it is equal to the scaled overscroll position.
-        int screenCenter = mOverScrollX + halfScreenSize;
-
-        if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
-            // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
-            // set it for the next frame
-            mForceScreenScrolled = false;
-            screenScrolled(screenCenter);
-            mLastScreenCenter = screenCenter;
-        }
-
         // Find out which screens are visible; as an optimization we only call draw on them
         final int pageCount = getChildCount();
         if (pageCount > 0) {
+            int halfScreenSize = getViewportWidth() / 2;
+            // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
+            // Otherwise it is equal to the scaled overscroll position.
+            int screenCenter = mOverScrollX + halfScreenSize;
+
+            if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
+                // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
+                // set it for the next frame
+                mForceScreenScrolled = false;
+                screenScrolled(screenCenter);
+                mLastScreenCenter = screenCenter;
+            }
+
             getVisiblePages(mTempVisiblePagesRange);
             final int leftScreen = mTempVisiblePagesRange[0];
             final int rightScreen = mTempVisiblePagesRange[1];
@@ -1392,13 +1428,13 @@
                  * being flinged.
                  */
                 final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
-                final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop);
+                final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop / 3);
 
                 if (finishedScrolling) {
                     mTouchState = TOUCH_STATE_REST;
-                    if (!mScroller.isFinished()) {
-                        mScrollAbortedFromIntercept = true;
-                        abortScrollerAnimation(false);
+                    if (!mScroller.isFinished() && !mFreeScroll) {
+                        setCurrentPage(getNextPage());
+                        pageEndMoving();
                     }
                 } else {
                     if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) {
@@ -1426,9 +1462,6 @@
 
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (mScrollAbortedFromIntercept) {
-                    snapToDestination();
-                }
                 resetTouchState();
                 break;
 
@@ -1570,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) {
@@ -1611,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();
     }
@@ -1640,7 +1664,7 @@
     }
 
     void updateFreescrollBounds() {
-        getOverviewModePages(mTempVisiblePagesRange);
+        getFreeScrollPageRange(mTempVisiblePagesRange);
         if (isLayoutRtl()) {
             mFreeScrollMinScrollX = getScrollForPage(mTempVisiblePagesRange[1]);
             mFreeScrollMaxScrollX = getScrollForPage(mTempVisiblePagesRange[0]);
@@ -1655,7 +1679,7 @@
 
         if (mFreeScroll) {
             updateFreescrollBounds();
-            getOverviewModePages(mTempVisiblePagesRange);
+            getFreeScrollPageRange(mTempVisiblePagesRange);
             if (getCurrentPage() < mTempVisiblePagesRange[0]) {
                 setCurrentPage(mTempVisiblePagesRange[0]);
             } else if (getCurrentPage() > mTempVisiblePagesRange[1]) {
@@ -1674,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++) {
@@ -1791,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()) {
@@ -1997,7 +2021,6 @@
         releaseVelocityTracker();
         endReordering();
         mCancelTap = false;
-        mScrollAbortedFromIntercept = false;
         mTouchState = TOUCH_STATE_REST;
         mActivePointerId = INVALID_POINTER;
     }
@@ -2115,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 {
@@ -2140,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;
         }
 
@@ -2174,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) {
@@ -2191,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;
@@ -2205,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 &&
@@ -2234,7 +2271,7 @@
 
         mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
 
-        notifyPageSwitchListener();
+        updatePageIndicator();
 
         // Trigger a compute() to finish switching pages if necessary
         if (immediate) {
@@ -2473,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
@@ -2610,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 8d8924b..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 java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.pm.ComponentInfo;
-import android.content.pm.ResolveInfo;
-import android.graphics.Bitmap;
-
-/**
- * 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 d2f897a..e6e11a3 100644
--- a/src/com/android/launcher3/PagedViewWidget.java
+++ b/src/com/android/launcher3/PagedViewWidget.java
@@ -30,7 +30,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import com.android.launcher3.R;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
 
 /**
  * The linear layout used strictly for the widget/wallpaper tab of the customization tray
@@ -129,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 75e5c98..0000000
--- a/src/com/android/launcher3/PreloadReceiver.java
+++ /dev/null
@@ -1,50 +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.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 Thread(new Runnable() {
-                @Override
-                public void run() {
-                    provider.loadDefaultFavoritesIfNecessary(workspaceResId);
-                }
-            }).start();
-        }
-    }
-}
diff --git a/src/com/android/launcher3/ScrimView.java b/src/com/android/launcher3/ScrimView.java
deleted file mode 100644
index 6831fe3..0000000
--- a/src/com/android/launcher3/ScrimView.java
+++ /dev/null
@@ -1,45 +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.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-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 dafabb8..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.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageInfo;
 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,17 +87,54 @@
      */
     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, 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) {
         super(info);
         title = info.title.toString();
@@ -83,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. */
@@ -97,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;
     }
@@ -125,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) {
@@ -177,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,
@@ -191,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 21c546d..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;
 
@@ -43,7 +49,7 @@
 /**
  * Various utilities shared amongst the Launcher's classes.
  */
-final class Utilities {
+public final class Utilities {
     private static final String TAG = "Launcher.Utilities";
 
     private static int sIconWidth = -1;
@@ -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,10 +67,18 @@
     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]
+    static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
+    public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
+
     /**
      * 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);
@@ -82,6 +92,23 @@
         icon.setBounds(0, 0, sIconTextureWidth, sIconTextureHeight);
     }
 
+    private static boolean isPropertyEnabled(String propertyName) {
+        return Log.isLoggable(propertyName, Log.VERBOSE);
+    }
+
+    public static boolean isRotationEnabled(Context c) {
+        boolean enableRotation = sForceEnableRotation ||
+                c.getResources().getBoolean(R.bool.allow_rotation);
+        return enableRotation;
+    }
+
+    /**
+     * 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)
@@ -111,7 +138,7 @@
     /**
      * Returns a bitmap suitable for the all apps view.
      */
-    static Bitmap createIconBitmap(Drawable icon, Context context) {
+    public static Bitmap createIconBitmap(Drawable icon, Context context) {
         synchronized (sCanvas) { // we share the statics :-(
             if (sIconWidth == -1) {
                 initStatics(context);
@@ -289,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) {
@@ -321,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();
@@ -342,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/WallpaperChangedReceiver.java b/src/com/android/launcher3/WallpaperChangedReceiver.java
new file mode 100644
index 0000000..2d5612f
--- /dev/null
+++ b/src/com/android/launcher3/WallpaperChangedReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class WallpaperChangedReceiver extends BroadcastReceiver {
+    public void onReceive(Context context, Intent data) {
+        LauncherAppState.setApplicationContext(context.getApplicationContext());
+        LauncherAppState appState = LauncherAppState.getInstance();
+        appState.onWallpaperChanged();
+    }
+}
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 8602606..774996e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -33,17 +33,22 @@
 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;
 import android.graphics.Region.Op;
 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;
@@ -55,10 +60,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.TextView;
@@ -66,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.
@@ -99,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;
@@ -107,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;
@@ -126,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
@@ -188,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;
 
@@ -203,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();
@@ -219,7 +231,7 @@
 
     // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
     private static final int FOLDER_CREATION_TIMEOUT = 0;
-    private static final int REORDER_TIMEOUT = 250;
+    public static final int REORDER_TIMEOUT = 350;
     private final Alarm mFolderCreationAlarm = new Alarm();
     private final Alarm mReorderAlarm = new Alarm();
     private FolderRingAnimator mDragFolderRingAnimator = null;
@@ -229,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;
@@ -269,6 +283,8 @@
     private int mLastChildCount = -1;
     private float mTransitionProgress;
 
+    float mOverScrollEffect = 0f;
+
     private Runnable mDeferredAction;
     private boolean mDeferDropAfterUninstall;
     private boolean mUninstallSuccessful;
@@ -338,6 +354,14 @@
     @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
+
+        CellLayout customScreen = getScreenWithId(CUSTOM_CONTENT_SCREEN_ID);
+        if (customScreen != null) {
+            View customContent = customScreen.getShortcutsAndWidgets().getChildAt(0);
+            if (customContent instanceof Insettable) {
+                ((Insettable) customContent).setInsets(mInsets);
+            }
+        }
     }
 
     // estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
@@ -383,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);
@@ -406,7 +440,6 @@
      * Initializes various states for this workspace.
      */
     protected void initWorkspace() {
-        Context context = getContext();
         mCurrentPage = mDefaultPage;
         Launcher.setScreen(mCurrentPage);
         LauncherAppState app = LauncherAppState.getInstance();
@@ -416,23 +449,19 @@
         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);
 
         mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
         mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+
+        // Set the wallpaper dimensions when Launcher starts up
+        setWallpaperDimension();
     }
 
     private void setupLayoutTransition() {
@@ -554,9 +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);
@@ -570,7 +601,6 @@
         mDefaultPage = mOriginalDefaultPage + 1;
 
         // Update the custom content hint
-        mLauncher.updateCustomContentHintVisibility();
         if (mRestorePage != INVALID_RESTORE_PAGE) {
             mRestorePage = mRestorePage + 1;
         } else {
@@ -599,7 +629,6 @@
         mDefaultPage = mOriginalDefaultPage - 1;
 
         // Update the custom content hint
-        mLauncher.updateCustomContentHintVisibility();
         if (mRestorePage != INVALID_RESTORE_PAGE) {
             mRestorePage = mRestorePage - 1;
         } else {
@@ -623,6 +652,12 @@
         if (customContent instanceof Insettable) {
             ((Insettable)customContent).setInsets(mInsets);
         }
+
+        // Verify that the child is removed from any existing parent.
+        if (customContent.getParent() instanceof ViewGroup) {
+            ViewGroup parent = (ViewGroup) customContent.getParent();
+            parent.removeView(customContent);
+        }
         customScreen.removeAllViews();
         customScreen.addViewToCellLayout(customContent, 0, 0, lp, true);
         mCustomContentDescription = description;
@@ -674,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);
 
@@ -690,26 +731,32 @@
             mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen);
             mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
 
-            // XXX: Do we need to update LM workspace screens here?
+            // Update the model if we have changed any screens
+            mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
             Launcher.addDumpLog(TAG, "11683562 -   extra empty screen: " + finalScreenId, true);
         }
     }
 
-    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;
         }
@@ -787,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);
@@ -843,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;
@@ -943,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) {
@@ -1009,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() {
@@ -1029,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;
         }
@@ -1048,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);
                 }
             }
@@ -1056,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++) {
@@ -1065,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);
@@ -1100,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;
@@ -1139,19 +1217,6 @@
                 enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
             }
         }
-
-        // Only show page outlines as we pan if we are on large screen
-        if (LauncherAppState.getInstance().isScreenLarge()) {
-            showOutlines();
-        }
-
-        // 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() {
@@ -1164,16 +1229,11 @@
         }
 
         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();
             }
-        } else {
-            // If we are not mid-dragging, hide the page outlines if we are on a large screen
-            if (LauncherAppState.getInstance().isScreenLarge()) {
-                hideOutlines();
-            }
         }
 
         if (mDelayedResizeRunnable != null) {
@@ -1194,12 +1254,12 @@
     @Override
     protected void notifyPageSwitchListener() {
         super.notifyPageSwitchListener();
-        Launcher.setScreen(mCurrentPage);
+        Launcher.setScreen(getNextPage());
 
         if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) {
             mCustomContentShowing = true;
             if (mCustomContentCallbacks != null) {
-                mCustomContentCallbacks.onShow();
+                mCustomContentCallbacks.onShow(false);
                 mCustomContentShowTime = System.currentTimeMillis();
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }
@@ -1211,9 +1271,6 @@
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }
         }
-        if (getPageIndicator() != null) {
-            getPageIndicator().setContentDescription(getPageIndicatorDescription());
-        }
     }
 
     protected CustomContentCallbacks getCustomContentCallbacks() {
@@ -1221,10 +1278,17 @@
     }
 
     protected void setWallpaperDimension() {
-        String spKey = WallpaperCropActivity.getSharedPreferencesKey();
-        SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
-        WallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
-                sp, mLauncher.getWindowManager(), mWallpaperManager);
+        new AsyncTask<Void, Void, Void>() {
+            public Void doInBackground(Void ... args) {
+                String spKey = WallpaperCropActivity.getSharedPreferencesKey();
+                SharedPreferences sp =
+                        mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+                LauncherWallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
+                        sp, mLauncher.getWindowManager(), mWallpaperManager,
+                        mLauncher.overrideWallpaperDimensions());
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
     }
 
     protected void snapToPage(int whichPage, Runnable r) {
@@ -1239,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);
     }
@@ -1335,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;
@@ -1379,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) {
@@ -1412,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);
@@ -1423,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);
@@ -1451,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;
@@ -1468,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;
@@ -1513,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++) {
@@ -1522,6 +1593,7 @@
                     float scrollProgress = getScrollProgress(screenCenter, child, i);
                     float alpha = 1 - Math.abs(scrollProgress);
                     child.getShortcutsAndWidgets().setAlpha(alpha);
+                    //child.setBackgroundAlphaMultiplier(1 - alpha);
                 }
             }
         }
@@ -1569,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);
@@ -1615,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) {
-                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() {
@@ -1682,6 +1747,16 @@
         AccessibilityManager am = (AccessibilityManager)
                 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
         sAccessibilityEnabled = am.isEnabled();
+
+        // Update wallpaper dimensions if they were changed since last onResume
+        // (we also always set the wallpaper dimensions in the constructor)
+        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
@@ -1695,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()) {
@@ -1729,7 +1791,7 @@
 
     @Override
     public int getDescendantFocusability() {
-        if (isSmall()) {
+        if (workspaceInModalState()) {
             return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
         }
         return super.getDescendantFocusability();
@@ -1747,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) {
@@ -1783,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) {
@@ -1921,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() {
@@ -1953,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();
@@ -1976,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();
@@ -2067,6 +2172,10 @@
         updateAccessibilityFlags();
     }
 
+    State getState() {
+        return mState;
+    }
+
     private void updateAccessibilityFlags() {
         int accessible = mState == State.NORMAL ?
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES :
@@ -2074,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;
         }
@@ -2087,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);
 
@@ -2113,23 +2233,17 @@
             enableFreeScroll();
         }
 
-
         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 {
@@ -2146,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;
@@ -2181,12 +2295,13 @@
         final View searchBar = mLauncher.getQsbBar();
         final View overviewPanel = mLauncher.getOverviewPanel();
         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++) {
@@ -2197,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);
                     }
@@ -2209,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(
@@ -2220,31 +2340,53 @@
                     }
                 }
             }
-            ObjectAnimator pageIndicatorAlpha = null;
-            if (getPageIndicator() != null) {
-                pageIndicatorAlpha = ObjectAnimator.ofFloat(getPageIndicator(), "alpha",
-                        finalHotseatAndPageIndicatorAlpha);
+            Animator pageIndicatorAlpha = null;
+            if (pageIndicator != null) {
+                pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
+                    .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
+                pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator));
+            } else {
+                // create a dummy animation so we don't need to do null checks later
+                pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
             }
-            ObjectAnimator hotseatAlpha = ObjectAnimator.ofFloat(hotseat, "alpha",
-                    finalHotseatAndPageIndicatorAlpha);
-            ObjectAnimator searchBarAlpha = ObjectAnimator.ofFloat(searchBar,
-                    "alpha", finalSearchBarAlpha);
-            ObjectAnimator overviewPanelAlpha = ObjectAnimator.ofFloat(overviewPanel,
-                    "alpha", finalOverviewPanelAlpha);
 
-            overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
+            Animator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
+                .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
             hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
+
+            Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
+                .alpha(finalSearchBarAlpha).withLayer();
             searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
 
+            Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
+                .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));
+                overviewPanelAlpha.setInterpolator(null);
             } else if (overviewToWorkspace) {
+                pageIndicatorAlpha.setInterpolator(null);
+                hotseatAlpha.setInterpolator(null);
                 overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
             }
 
-            if (getPageIndicator() != null) {
-                pageIndicatorAlpha.addListener(new AlphaUpdateListener(getPageIndicator()));
-            }
+            overviewPanelAlpha.setDuration(duration);
+            pageIndicatorAlpha.setDuration(duration);
+            hotseatAlpha.setDuration(duration);
+            searchBarAlpha.setDuration(duration);
 
             anim.play(overviewPanelAlpha);
             anim.play(hotseatAlpha);
@@ -2256,9 +2398,9 @@
             AlphaUpdateListener.updateVisibility(overviewPanel);
             hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
             AlphaUpdateListener.updateVisibility(hotseat);
-            if (getPageIndicator() != null) {
-                getPageIndicator().setAlpha(finalHotseatAndPageIndicatorAlpha);
-                AlphaUpdateListener.updateVisibility(getPageIndicator());
+            if (pageIndicator != null) {
+                pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
+                AlphaUpdateListener.updateVisibility(pageIndicator);
             }
             searchBar.setAlpha(finalSearchBarAlpha);
             AlphaUpdateListener.updateVisibility(searchBar);
@@ -2269,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;
     }
@@ -2383,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();
     }
 
@@ -2413,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) {
@@ -2433,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);
@@ -2457,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;
     }
@@ -2481,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;
     }
 
@@ -2497,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(),
@@ -2513,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;
     }
@@ -2534,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;
@@ -2571,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;
@@ -2581,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)) {
@@ -2602,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);
@@ -2615,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));
     }
 
     /**
@@ -2665,17 +2830,18 @@
                     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;
             }
 
             int[] resultSpan = new int[2];
-            mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+            mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
                     (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
                     null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);
             boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
@@ -2880,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;
                 }
 
@@ -2901,7 +3065,7 @@
                 }
 
                 int[] resultSpan = new int[2];
-                mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+                mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
                         (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell,
                         mTargetCell, resultSpan, CellLayout.MODE_ON_DROP);
 
@@ -2927,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);
                     }
@@ -2992,7 +3161,6 @@
                     if (finalResizeRunnable != null) {
                         finalResizeRunnable.run();
                     }
-                    removeExtraEmptyScreen(true, null, 0, true);
                 }
             };
             mAnimatingViewIntoPlace = true;
@@ -3061,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();
         }
     }
 
@@ -3074,20 +3240,17 @@
         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();
         display.getCurrentSizeRange(smallestSize, largestSize);
         int countX = (int) grid.numColumns;
         int countY = (int) grid.numRows;
-        int constrainedLongEdge = largestSize.y;
-        int constrainedShortEdge = smallestSize.y;
         if (orientation == CellLayout.LANDSCAPE) {
             if (mLandscapeCellLayoutMetrics == null) {
                 Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE);
-                int width = constrainedLongEdge - padding.left - padding.right;
-                int height = constrainedShortEdge - padding.top - padding.bottom;
+                int width = largestSize.x - padding.left - padding.right;
+                int height = smallestSize.y - padding.top - padding.bottom;
                 mLandscapeCellLayoutMetrics = new Rect();
                 mLandscapeCellLayoutMetrics.set(
                         grid.calculateCellWidth(width, countX),
@@ -3097,8 +3260,8 @@
         } else if (orientation == CellLayout.PORTRAIT) {
             if (mPortraitCellLayoutMetrics == null) {
                 Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT);
-                int width = constrainedShortEdge - padding.left - padding.right;
-                int height = constrainedLongEdge - padding.top - padding.bottom;
+                int width = smallestSize.x - padding.left - padding.right;
+                int height = largestSize.y - padding.top - padding.bottom;
                 mPortraitCellLayoutMetrics = new Rect();
                 mPortraitCellLayoutMetrics.set(
                         grid.calculateCellWidth(width, countX),
@@ -3142,6 +3305,7 @@
         if (!mIsPageMoving) {
             hideOutlines();
         }
+        mLauncher.getDragLayer().hidePageHints();
     }
 
     void setCurrentDropLayout(CellLayout layout) {
@@ -3384,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");
@@ -3397,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();
@@ -3483,6 +3653,11 @@
                     && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX ||
                     mLastReorderY != reorderY)) {
 
+                int[] resultSpan = new int[2];
+                mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
+                        (int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY,
+                        child, mTargetCell, resultSpan, CellLayout.MODE_SHOW_REORDER_HINT);
+
                 // Otherwise, if we aren't adding to or creating a folder and there's no pending
                 // reorder, then we schedule a reorder
                 ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
@@ -3587,7 +3762,7 @@
             mLastReorderX = mTargetCell[0];
             mLastReorderY = mTargetCell[1];
 
-            mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0],
+            mTargetCell = mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
                 (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
                 child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER);
 
@@ -3643,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);
             }
         };
 
@@ -3697,7 +3867,7 @@
                     minSpanY = item.minSpanY;
                 }
                 int[] resultSpan = new int[2];
-                mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+                mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0],
                         (int) mDragViewVisualCenter[1], minSpanX, minSpanY, info.spanX, info.spanY,
                         null, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP_EXTERNAL);
 
@@ -3711,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) {
@@ -3789,21 +3964,22 @@
 
             if (touchXY != null) {
                 // when dragging and dropping, just find the closest free spot
-                mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+                mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0],
                         (int) mDragViewVisualCenter[1], 1, 1, 1, 1,
                         null, mTargetCell, null, CellLayout.MODE_ON_DROP_EXTERNAL);
             } 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
@@ -3826,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;
     }
@@ -3961,7 +4137,7 @@
         return mDragInfo;
     }
 
-    public int getRestorePage() {
+    public int getCurrentPageOffsetFromCustomContent() {
         return getNextPage() - numCustomPages();
     }
 
@@ -3983,7 +4159,6 @@
         // hardware layers on children are enabled on startup, but should be disabled until
         // needed
         updateChildrenLayersEnabled(false);
-        setWallpaperDimension();
     }
 
     /**
@@ -4008,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;
@@ -4024,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) {
@@ -4205,6 +4384,16 @@
     }
 
     @Override
+    public boolean supportsAppInfoDropTarget() {
+        return false;
+    }
+
+    @Override
+    public boolean supportsDeleteDropTarget() {
+        return true;
+    }
+
+    @Override
     public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
         // Do nothing
     }
@@ -4236,7 +4425,9 @@
         if (mSavedStates != null) {
             mRestoredPages.add(child);
             CellLayout cl = (CellLayout) getChildAt(child);
-            cl.restoreInstanceState(mSavedStates);
+            if (cl != null) {
+                cl.restoreInstanceState(mSavedStates);
+            }
         }
     }
 
@@ -4253,7 +4444,7 @@
 
     @Override
     public void scrollLeft() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             super.scrollLeft();
         }
         Folder openFolder = getOpenFolder();
@@ -4264,7 +4455,7 @@
 
     @Override
     public void scrollRight() {
-        if (!isSmall() && !mIsSwitchingState) {
+        if (!workspaceInModalState() && !mIsSwitchingState) {
             super.scrollRight();
         }
         Folder openFolder = getOpenFolder();
@@ -4286,7 +4477,7 @@
         }
 
         boolean result = false;
-        if (!isSmall() && !mIsSwitchingState && getOpenFolder() == null) {
+        if (!workspaceInModalState() && !mIsSwitchingState && getOpenFolder() == null) {
             mInScrollArea = true;
 
             final int page = getNextPage() +
@@ -4378,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);
 
@@ -4448,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;
                 }
@@ -4458,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) {
@@ -4472,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();
@@ -4494,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)) {
@@ -4507,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;
                         }
@@ -4545,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 {
@@ -4663,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());
+    }
+}
+
diff --git a/update_gallery_files.py b/update_gallery_files.py
index ef4e8c9..738d225 100644
--- a/update_gallery_files.py
+++ b/update_gallery_files.py
@@ -49,6 +49,6 @@
     dir = os.path.dirname(file_path)
     if file_path.find('exif') != -1 or file_path.find('common') != -1:
         file_path = 'gallerycommon/' + file_path
-    cmd = 'cp %s/%s %s/' % (gallery_dir, file_path, dir)
+    cmd = 'cp %s/%s WallpaperPicker/%s/' % (gallery_dir, file_path, dir)
     print cmd
     os.system(cmd)
diff --git a/update_system_wallpaper_cropper.py b/update_system_wallpaper_cropper.py
index 5d24f6f..44cbcc9 100644
--- a/update_system_wallpaper_cropper.py
+++ b/update_system_wallpaper_cropper.py
@@ -5,42 +5,43 @@
 # necessary so do this with care
 import os
 import sys
+src_dir = "WallpaperPicker/src/"
 files = """
 src/android/util/Pools.java
-src/com/android/gallery3d/util/IntArray.java
-src/com/android/gallery3d/common/Utils.java
-src/com/android/gallery3d/exif/ByteBufferInputStream.java
-src/com/android/gallery3d/exif/CountedDataInputStream.java
-src/com/android/gallery3d/exif/ExifData.java
-src/com/android/gallery3d/exif/ExifInterface.java
-src/com/android/gallery3d/exif/ExifInvalidFormatException.java
-src/com/android/gallery3d/exif/ExifModifier.java
-src/com/android/gallery3d/exif/ExifOutputStream.java
-src/com/android/gallery3d/exif/ExifParser.java
-src/com/android/gallery3d/exif/ExifReader.java
-src/com/android/gallery3d/exif/ExifTag.java
-src/com/android/gallery3d/exif/IfdData.java
-src/com/android/gallery3d/exif/IfdId.java
-src/com/android/gallery3d/exif/JpegHeader.java
-src/com/android/gallery3d/exif/OrderedDataOutputStream.java
-src/com/android/gallery3d/exif/Rational.java
-src/com/android/gallery3d/glrenderer/BasicTexture.java
-src/com/android/gallery3d/glrenderer/BitmapTexture.java
-src/com/android/gallery3d/glrenderer/GLCanvas.java
-src/com/android/gallery3d/glrenderer/GLES20Canvas.java
-src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
-src/com/android/gallery3d/glrenderer/GLId.java
-src/com/android/gallery3d/glrenderer/GLPaint.java
-src/com/android/gallery3d/glrenderer/RawTexture.java
-src/com/android/gallery3d/glrenderer/Texture.java
-src/com/android/gallery3d/glrenderer/UploadedTexture.java
-src/com/android/photos/BitmapRegionTileSource.java
-src/com/android/photos/views/BlockingGLTextureView.java
-src/com/android/photos/views/TiledImageRenderer.java
-src/com/android/photos/views/TiledImageView.java
-src/com/android/gallery3d/common/BitmapUtils.java
-src/com/android/launcher3/CropView.java
-src/com/android/launcher3/WallpaperCropActivity.java
+com/android/gallery3d/util/IntArray.java
+com/android/gallery3d/common/Utils.java
+com/android/gallery3d/exif/ByteBufferInputStream.java
+com/android/gallery3d/exif/CountedDataInputStream.java
+com/android/gallery3d/exif/ExifData.java
+com/android/gallery3d/exif/ExifInterface.java
+com/android/gallery3d/exif/ExifInvalidFormatException.java
+com/android/gallery3d/exif/ExifModifier.java
+com/android/gallery3d/exif/ExifOutputStream.java
+com/android/gallery3d/exif/ExifParser.java
+com/android/gallery3d/exif/ExifReader.java
+com/android/gallery3d/exif/ExifTag.java
+com/android/gallery3d/exif/IfdData.java
+com/android/gallery3d/exif/IfdId.java
+com/android/gallery3d/exif/JpegHeader.java
+com/android/gallery3d/exif/OrderedDataOutputStream.java
+com/android/gallery3d/exif/Rational.java
+com/android/gallery3d/glrenderer/BasicTexture.java
+com/android/gallery3d/glrenderer/BitmapTexture.java
+com/android/gallery3d/glrenderer/GLCanvas.java
+com/android/gallery3d/glrenderer/GLES20Canvas.java
+com/android/gallery3d/glrenderer/GLES20IdImpl.java
+com/android/gallery3d/glrenderer/GLId.java
+com/android/gallery3d/glrenderer/GLPaint.java
+com/android/gallery3d/glrenderer/RawTexture.java
+com/android/gallery3d/glrenderer/Texture.java
+com/android/gallery3d/glrenderer/UploadedTexture.java
+com/android/photos/BitmapRegionTileSource.java
+com/android/photos/views/BlockingGLTextureView.java
+com/android/photos/views/TiledImageRenderer.java
+com/android/photos/views/TiledImageView.java
+com/android/gallery3d/common/BitmapUtils.java
+com/android/launcher3/CropView.java
+com/android/launcher3/WallpaperCropActivity.java
 """
 
 if len(sys.argv) != 2:
@@ -48,8 +49,10 @@
     exit()
 framework_dir = sys.argv[1] + "/packages/WallpaperCropper"
 for file_path in files.split():
+    file_path = src_dir + file_path
     dir = os.path.dirname(file_path)
     dir = dir.replace("launcher3", "wallpapercropper")
+    dir = dir.replace(src_dir, "src/")
     cmd = 'cp %s %s/%s' % (file_path, framework_dir, dir)
     print cmd
     os.system(cmd)
diff --git a/util/com/android/launcher3/DecoderRing.java b/util/com/android/launcher3/DecoderRing.java
index 1d9e0de..86431d9 100644
--- a/util/com/android/launcher3/DecoderRing.java
+++ b/util/com/android/launcher3/DecoderRing.java
@@ -34,159 +34,283 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.lang.System;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.zip.CRC32;
 
+import javax.xml.bind.DatatypeConverter;
+
+
 /**
- * Commandline utility for decoding protos written to the android logs during debugging.
+ * Commandline utility for decoding Launcher3 backup protocol buffers.
  *
- * base64 -D icon.log > icon.bin
- * java -classpath $ANDROID_HOST_OUT/framework/protoutil.jar:$ANDROID_HOST_OUT/../common/obj/JAVA_LIBRARIES/host-libprotobuf-java-2.3.0-nano_intermediates/javalib.jar \
- *   com.android.launcher3.DecoderRing -i icon.bin
+ * <P>When using com.android.internal.backup.LocalTransport, the file names are base64-encoded Key
+ * protocol buffers with a prefix, that have been base64-encoded again by the transport:
+ * <pre>
+ *     echo "TDpDQUlnL0pxVTVnOD0=" | launcher_protoutil -k
+ * </pre>
  *
- * TODO: write a wrapper to setup the classpath
+ * <P>This tool understands these file names and will use the embedded Key to detect the type and
+ * extract the payload automatically:
+ * <pre>
+ *     launcher_protoutil /tmp/TDpDQUlnL0pxVTVnOD0=
+ * </pre>
+ *
+ * <P>With payload debugging enabled, base64-encoded protocol buffers will be written to the logs.
+ * Copy the encoded snippet from the log, and specify the type explicitly, with the Logs flags:
+ * <pre>
+ *    echo "CAEYLiCJ9JKsDw==" | launcher_protoutil -L -k
+ * </pre>
+ * For backup payloads it is more convenient to copy the log snippet to a file:
+ * <pre>
+ *    launcher_protoutil -L -f favorite.log
+ * </pre>
  */
 class DecoderRing {
+
+    public static final String STANDARD_IN = "**stdin**";
+
+    private static Class[] TYPES = {
+            Key.class,
+            Favorite.class,
+            Screen.class,
+            Resource.class,
+            Widget.class
+    };
+    static final int ICON_TYPE_BITMAP = 1;
+
     public static void main(String[ ] args)
             throws Exception {
-        File source = null;
-        Class type = Key.class;
+        Class defaultType = null;
+        boolean extractImages = false;
+        boolean fromLogs = false;
         int skip = 0;
+        List<File> files = new LinkedList<File>();
+        boolean verbose = false;
 
         for (int i = 0; i < args.length; i++) {
             if ("-k".equals(args[i])) {
-                type = Key.class;
+                defaultType = Key.class;
             } else if ("-f".equals(args[i])) {
-                type = Favorite.class;
+                defaultType = Favorite.class;
             } else if ("-j".equals(args[i])) {
-                type = Journal.class;
+                defaultType = Journal.class;
             } else if ("-i".equals(args[i])) {
-                type = Resource.class;
+                defaultType = Resource.class;
             } else if ("-s".equals(args[i])) {
-                type = Screen.class;
+                defaultType = Screen.class;
             } else if ("-w".equals(args[i])) {
-                type = Widget.class;
+                defaultType = Widget.class;
             } else if ("-S".equals(args[i])) {
                 if ((i + 1) < args.length) {
                     skip = Integer.valueOf(args[++i]);
                 } else {
                     usage(args);
                 }
+            } else if ("-x".equals(args[i])) {
+                extractImages = true;
+            } else if ("-v".equals(args[i])) {
+                verbose = true;
+            } else if ("-L".equals(args[i])) {
+                fromLogs = true;
             } else if (args[i] != null && !args[i].startsWith("-")) {
-                source = new File(args[i]);
+                files.add(new File(args[i]));
             } else {
                 System.err.println("Unsupported flag: " + args[i]);
                 usage(args);
             }
         }
 
+        if (defaultType == null && files.isEmpty()) {
+            // can't infer file type without the key
+            usage(args);
+        }
 
-        // read in the bytes
-        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
-        BufferedInputStream input = null;
-        if (source == null) {
-            input = new BufferedInputStream(System.in);
-        } else {
+        if (files.size() > 1 && defaultType != null) {
+            System.err.println("Explicit type ignored for multiple files.");
+            defaultType = null;
+        }
+
+        if (files.isEmpty()) {
+            files.add(new File(STANDARD_IN));
+        }
+
+        for (File source : files) {
+            Class type = null;
+            if (defaultType == null) {
+                Key key = decodeKey(source.getName().getBytes(), fromLogs);
+                if (key != null) {
+                    type = TYPES[key.type];
+                    if (verbose) {
+                        System.err.println(source.getName() + " is a " + type.getSimpleName());
+                        System.out.println(key.toString());
+                    }
+                }
+            } else {
+                type = defaultType;
+            }
+
+            // read in the bytes
+            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+            BufferedInputStream input = null;
+            if (source.getName() == STANDARD_IN) {
+                input = new BufferedInputStream(System.in);
+            } else {
+                try {
+                    input = new BufferedInputStream(new FileInputStream(source));
+                } catch (FileNotFoundException e) {
+                    System.err.println("failed to open file: " + source + ", " + e);
+                    System.exit(1);
+                }
+            }
+            byte[] buffer = new byte[1024];
             try {
-                input = new BufferedInputStream(new FileInputStream(source));
-            } catch (FileNotFoundException e) {
-                System.err.println("failed to open file: " + source + ", " + e);
+                while (input.available() > 0) {
+                    int n = input.read(buffer);
+                    int offset = 0;
+                    if (skip > 0) {
+                        offset = Math.min(skip, n);
+                        n -= offset;
+                        skip -= offset;
+                    }
+                    if (n > 0) {
+                        byteStream.write(buffer, offset, n);
+                    }
+                }
+            } catch (IOException e) {
+                System.err.println("failed to read input: " + e);
                 System.exit(1);
             }
-        }
-        byte[] buffer = new byte[1024];
-        try {
-            while (input.available() > 0) {
-                int n = input.read(buffer);
-                int offset = 0;
-                if (skip > 0) {
-                    offset = Math.min(skip, n);
-                    n -= offset;
-                    skip -= offset;
+
+            MessageNano proto = null;
+            byte[] payload = byteStream.toByteArray();
+            if (type == Key.class) {
+                proto = decodeKey(payload, fromLogs);
+            } else if (type != null) {
+                proto = decodeBackupData(payload, type, fromLogs);
+            }
+
+            // Generic string output
+            if (proto != null) {
+                System.out.println(proto.toString());
+            }
+
+            if (extractImages) {
+                String prefix = "stdin";
+                if (source != null) {
+                    prefix = source.getName();
                 }
-                if (n > 0) {
-                    byteStream.write(buffer, offset, n);
+                // save off the icon bits in a file for inspection
+                if (proto instanceof Resource) {
+                    Resource icon = (Resource) proto;
+                    writeImageData(icon.data, prefix + ".png");
+                }
+
+                // save off the icon bits in a file for inspection
+                if (proto instanceof Favorite) {
+                    Favorite favorite = (Favorite) proto;
+                    if (favorite.iconType == ICON_TYPE_BITMAP) {
+                        writeImageData(favorite.icon, prefix + ".png");
+                    }
+                }
+
+                // save off the widget icon and preview bits in files for inspection
+                if (proto instanceof Widget) {
+                    Widget widget = (Widget) proto;
+                    if (widget.icon != null) {
+                        writeImageData(widget.icon.data, prefix + "_icon.png");
+                    }
+                    if (widget.preview != null) {
+                        writeImageData(widget.preview.data, prefix + "_preview.png");
+                    }
                 }
             }
-        } catch (IOException e) {
-            System.err.println("failed to read input: " + e);
+        }
+        System.exit(0);
+    }
+
+    // In logcat, backup data is base64 encoded, but in localtransport files it is raw
+    private static MessageNano decodeBackupData(byte[] payload, Class type, boolean fromLogs)
+            throws InstantiationException, IllegalAccessException {
+        MessageNano proto;// other types are wrapped in a checksum message
+        CheckedMessage wrapper = new CheckedMessage();
+        try {
+            if (fromLogs) {
+                payload = DatatypeConverter.parseBase64Binary(new String(payload));
+            }
+            MessageNano.mergeFrom(wrapper, payload);
+        } catch (InvalidProtocolBufferNanoException e) {
+            System.err.println("failed to parse wrapper: " + e);
             System.exit(1);
         }
-        System.err.println("read this many bytes: " + byteStream.size());
 
-        MessageNano proto = null;
-        if (type == Key.class) {
-            Key key = new Key();
-            try {
-                key = Key.parseFrom(byteStream.toByteArray());
-            } catch (InvalidProtocolBufferNanoException e) {
-                System.err.println("failed to parse proto: " + e);
-                System.exit(1);
-            }
-            // keys are self-checked
-            if (key.checksum != checkKey(key)) {
-                System.err.println("key ckecksum failed");
-                System.exit(1);
-            }
-            proto = key;
-        } else {
-            // other types are wrapped in a checksum message
-            CheckedMessage wrapper = new CheckedMessage();
-            try {
-                MessageNano.mergeFrom(wrapper, byteStream.toByteArray());
-            } catch (InvalidProtocolBufferNanoException e) {
-                System.err.println("failed to parse wrapper: " + e);
-                System.exit(1);
-            }
-            CRC32 checksum = new CRC32();
-            checksum.update(wrapper.payload);
-            if (wrapper.checksum != checksum.getValue()) {
-                System.err.println("wrapper ckecksum failed");
-                System.exit(1);
-            }
-            // decode the actual message
-            proto = (MessageNano) type.newInstance();
-            try {
-                MessageNano.mergeFrom(proto, wrapper.payload);
-            } catch (InvalidProtocolBufferNanoException e) {
-                System.err.println("failed to parse proto: " + e);
-                System.exit(1);
-            }
+        CRC32 checksum = new CRC32();
+        checksum.update(wrapper.payload);
+        if (wrapper.checksum != checksum.getValue()) {
+            System.err.println("wrapper checksum failed");
+            System.exit(1);
         }
 
-        // Generic string output
-        System.out.println(proto.toString());
+        // decode the actual message
+        proto = (MessageNano) type.newInstance();
+        try {
+            MessageNano.mergeFrom(proto, wrapper.payload);
+        } catch (InvalidProtocolBufferNanoException e) {
+            System.err.println("failed to parse proto: " + e);
+            System.exit(1);
+        }
+        return proto;
+    }
 
-        // save off the icon bits in a file for inspection
-        if (proto instanceof Resource) {
-            Resource icon = (Resource) proto;
-            final String path = "icon.webp";
-            FileOutputStream iconFile = new FileOutputStream(path);
-            iconFile.write(icon.data);
-            iconFile.close();
+    // In logcat, keys are base64 encoded with no prefix.
+    // The localtransport adds a prefix and the base64 encodes the whole thing again.
+    private static Key decodeKey(byte[] payload, boolean fromLogs) {
+        Key key = new Key();
+        try {
+            String encodedKey = new String(payload);
+            if (!fromLogs) {
+                byte[] rawKey = DatatypeConverter.parseBase64Binary(encodedKey);
+                if (rawKey[0] != 'L' || rawKey[1] != ':') {
+                    System.err.println(encodedKey + " is not a launcher backup key.");
+                    return null;
+                }
+                encodedKey = new String(rawKey, 2, rawKey.length - 2);
+            }
+            byte[] keyProtoData = DatatypeConverter.parseBase64Binary(encodedKey);
+            key = Key.parseFrom(keyProtoData);
+        } catch (InvalidProtocolBufferNanoException protoException) {
+            System.err.println("failed to extract key from filename: " + protoException);
+            return null;
+        } catch (IllegalArgumentException base64Exception) {
+            System.err.println("failed to extract key from filename: " + base64Exception);
+            return null;
+        }
+
+        // keys are self-checked
+        if (key.checksum != checkKey(key)) {
+            System.err.println("key ckecksum failed");
+            return null;
+        }
+        return key;
+    }
+
+    private static void writeImageData(byte[] data, String path) {
+        FileOutputStream iconFile = null;
+        try {
+            iconFile = new FileOutputStream(path);
+            iconFile.write(data);
             System.err.println("wrote " + path);
-        }
-
-        // save off the widget icon and preview bits in files for inspection
-        if (proto instanceof Widget) {
-            Widget widget = (Widget) proto;
-            if (widget.icon != null) {
-                final String path = "widget_icon.webp";
-                FileOutputStream iconFile = new FileOutputStream(path);
-                iconFile.write(widget.icon.data);
-                iconFile.close();
-                System.err.println("wrote " + path);
-            }
-            if (widget.preview != null) {
-                final String path = "widget_preview.webp";
-                FileOutputStream iconFile = new FileOutputStream(path);
-                iconFile.write(widget.preview.data);
-                iconFile.close();
-                System.err.println("wrote " + path);
+        } catch (IOException e) {
+            System.err.println("failed to write image file: " + e);
+        } finally {
+            if (iconFile != null) {
+                try {
+                    iconFile.close();
+                } catch (IOException e) {
+                    System.err.println("failed to close the image file: " + e);
+                }
             }
         }
-
-        // success
-        System.exit(0);
     }
 
     private static long checkKey(Key key) {
@@ -201,13 +325,16 @@
     }
 
     private static void usage(String[] args) {
-        System.err.println("DecoderRing type [input]");
+        System.err.println("launcher_protoutil [-x] [-S b] [-k|-f|-i|-s|-w] [filename]");
         System.err.println("\t-k\tdecode a key");
         System.err.println("\t-f\tdecode a favorite");
         System.err.println("\t-i\tdecode a icon");
         System.err.println("\t-s\tdecode a screen");
         System.err.println("\t-w\tdecode a widget");
-        System.err.println("\t-s b\tskip b bytes");
+        System.err.println("\t-S b\tskip b bytes");
+        System.err.println("\t-x\textract image data to files");
+        System.err.println("\t-v\tprint key type data, as well as payload");
+        System.err.println("\t-l\texpect data from logcat, instead of the local transport");
         System.err.println("\tfilename\tread from filename, not stdin");
         System.exit(1);
     }
diff --git a/util/etc/launcher_protoutil b/util/etc/launcher_protoutil
new file mode 100644
index 0000000..833b583
--- /dev/null
+++ b/util/etc/launcher_protoutil
@@ -0,0 +1,83 @@
+#!/bin/bash
+#
+# 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=launcher_protoutil_lib.jar
+libdir="$progdir"
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    # set jar location for the Android tree case
+    libdir=`dirname "$progdir"`/framework
+fi
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+# By default, give decoder a max heap size of 1 gig. This can be overridden
+# by using a "-J" option (see below).
+defaultMx="-Xmx1024M"
+
+# The following will extract any initial parameters of the form
+# "-J<stuff>" from the command line and pass them to the Java
+# invocation (instead of to the decoder). This makes it possible for
+# you to add a command-line parameter such as "-JXmx256M" in your
+# scripts, for example. "java" (with no args) and "java -X" give a
+# summary of available options.
+
+javaOpts=""
+
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "x$1" : 'x-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then
+        defaultMx="no"
+    fi
+    shift
+done
+
+if [ "${defaultMx}" != "no" ]; then
+    javaOpts="${javaOpts} ${defaultMx}"
+fi
+
+if [ "$OSTYPE" = "cygwin" ]; then
+    # For Cygwin, convert the jarfile path into native Windows style.
+    jarpath=`cygpath -w "$libdir/$jarfile"`
+else
+    jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/util/etc/manifest.txt b/util/etc/manifest.txt
new file mode 100644
index 0000000..84842ed
--- /dev/null
+++ b/util/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.launcher3.DecoderRing