Import translations. DO NOT MERGE
am: 21c2d8f244  -s ours

* commit '21c2d8f244dae711b12339cc6e643cd34ef8dcd6':
  Import translations. DO NOT MERGE

Change-Id: I20291932d55ac2f053b239cb8c0b87c3453b26e6
diff --git a/Android.mk b/Android.mk
index 1dde46b..5605fdb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,7 +33,7 @@
 
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res \
     $(LOCAL_PATH)/res \
-    prebuilts/sdk/current/support/v7/recyclerview/res
+    frameworks/support/v7/recyclerview/res
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
diff --git a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
index 8e349b7..2b39b09 100644
--- a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -28,5 +28,6 @@
     android:drawableLeft="@drawable/ic_actionbar_accept"
     android:drawablePadding="8dp"
     android:gravity="start|center_vertical"
-    android:text="@string/wallpaper_instructions">
+    android:text="@string/wallpaper_instructions"
+    android:enabled="false">
 </com.android.launcher3.AlphaDisableableButton>
diff --git a/WallpaperPicker/res/values-af/strings.xml b/WallpaperPicker/res/values-af/strings.xml
index 8d96188..c926f48 100644
--- a/WallpaperPicker/res/values-af/strings.xml
+++ b/WallpaperPicker/res/values-af/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"My foto\'s"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Muurpapiere"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Snoei muurpapier"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-am/strings.xml b/WallpaperPicker/res/values-am/strings.xml
index f73622c..1b067d4 100644
--- a/WallpaperPicker/res/values-am/strings.xml
+++ b/WallpaperPicker/res/values-am/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"የእኔ ፎቶዎች"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"የግድግዳ ወረቀቶች"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ልጣፍ  ይከርክሙ"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ar/strings.xml b/WallpaperPicker/res/values-ar/strings.xml
index 457e534..354b344 100644
--- a/WallpaperPicker/res/values-ar/strings.xml
+++ b/WallpaperPicker/res/values-ar/strings.xml
@@ -37,4 +37,7 @@
     <string name="pick_image" msgid="3189640419551368385">"صوري"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"الخلفيات"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"اقتصاص الخلفية"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"الشاشة الرئيسية"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"شاشة التأمين"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"الشاشة الرئيسية وشاشة التأمين"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-az-rAZ/strings.xml b/WallpaperPicker/res/values-az-rAZ/strings.xml
index 9c084e8..cb894c9 100644
--- a/WallpaperPicker/res/values-az-rAZ/strings.xml
+++ b/WallpaperPicker/res/values-az-rAZ/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Fotolarım"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Divar kağızları"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Divar kağızını kəsin"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-b+sr+Latn/strings.xml b/WallpaperPicker/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..2ac0803
--- /dev/null
+++ b/WallpaperPicker/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,43 @@
+<?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">"Podesi pozadinu"</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 pozadinu"</string>
+    <string name="wallpaper_set_fail" msgid="7023180794008631780">"Učitavanje slike kao pozadine nije uspelo"</string>
+    <plurals name="number_of_items_selected" formatted="false" msgid="4578652015328149361">
+      <item quantity="one">Izabrana je %1$d stavka</item>
+      <item quantity="few">Izabrane su %1$d stavke</item>
+      <item quantity="other">Izabrano je %1$d stavki</item>
+    </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Pozadina %1$d od %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Izabrana je <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
+    <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Pozadine"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Opseci pozadinu"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
+</resources>
diff --git a/WallpaperPicker/res/values-be-rBY/strings.xml b/WallpaperPicker/res/values-be-rBY/strings.xml
new file mode 100644
index 0000000..c78814a
--- /dev/null
+++ b/WallpaperPicker/res/values-be-rBY/strings.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 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>
+    <string name="wallpaper_set_fail" msgid="7023180794008631780">"Не атрымалася задаць відарыс як шпалеры"</string>
+    <plurals name="number_of_items_selected" formatted="false" msgid="4578652015328149361">
+      <item quantity="one">%1$d выбраны</item>
+      <item quantity="few">%1$d выбраны</item>
+      <item quantity="many">%1$d выбраны</item>
+      <item quantity="other">%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="3189640419551368385">"Мае фатаграфii"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Шпалеры"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Абрэзаць шпалеры"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
+</resources>
diff --git a/WallpaperPicker/res/values-bg/strings.xml b/WallpaperPicker/res/values-bg/strings.xml
index 2af3123..bd49629 100644
--- a/WallpaperPicker/res/values-bg/strings.xml
+++ b/WallpaperPicker/res/values-bg/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"Моите снимки"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Тапети"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Подрязване на тапета"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"Начален екран"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"Заключен екран"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"Начален и заключен екран"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-bn-rBD/strings.xml b/WallpaperPicker/res/values-bn-rBD/strings.xml
index ab35daf..79a370e 100644
--- a/WallpaperPicker/res/values-bn-rBD/strings.xml
+++ b/WallpaperPicker/res/values-bn-rBD/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"আমার ফটো"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ওয়ালপেপারগুলি"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ওয়ালপেপার কাটছাঁট করুন"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-bs-rBA/strings.xml b/WallpaperPicker/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..304bc57
--- /dev/null
+++ b/WallpaperPicker/res/values-bs-rBA/strings.xml
@@ -0,0 +1,43 @@
+<?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 pozadinu"</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 pozadinu"</string>
+    <string name="wallpaper_set_fail" msgid="7023180794008631780">"Nije moguće postaviti sliku kao pozadinu"</string>
+    <plurals name="number_of_items_selected" formatted="false" msgid="4578652015328149361">
+      <item quantity="one">odabran je %1$d</item>
+      <item quantity="few">odabrana su %1$d</item>
+      <item quantity="other">odabrano je %1$d</item>
+    </plurals>
+    <string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Pozadina %1$d od %2$d"</string>
+    <string name="announce_selection" msgid="123723511662250539">"Odabrano: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
+    <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Pozadine"</string>
+    <string name="crop_wallpaper" msgid="4882870800623585836">"Izreži pozadinsku sliku"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
+</resources>
diff --git a/WallpaperPicker/res/values-ca/strings.xml b/WallpaperPicker/res/values-ca/strings.xml
index 652dced..3110e34 100644
--- a/WallpaperPicker/res/values-ca/strings.xml
+++ b/WallpaperPicker/res/values-ca/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Les meves fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fons de pantalla"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Retallar fons de pantalla"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-cs/strings.xml b/WallpaperPicker/res/values-cs/strings.xml
index 58509e7..8ec211a 100644
--- a/WallpaperPicker/res/values-cs/strings.xml
+++ b/WallpaperPicker/res/values-cs/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Moje fotografie"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Oříznutí tapety"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-da/strings.xml b/WallpaperPicker/res/values-da/strings.xml
index 867cbc9..58409b8 100644
--- a/WallpaperPicker/res/values-da/strings.xml
+++ b/WallpaperPicker/res/values-da/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mine billeder"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Baggrunde"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Beskær baggrunden"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-de/strings.xml b/WallpaperPicker/res/values-de/strings.xml
index 53c1002..175e6a7 100644
--- a/WallpaperPicker/res/values-de/strings.xml
+++ b/WallpaperPicker/res/values-de/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Meine Fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Hintergründe"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Hintergrund zuschneiden"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-el/strings.xml b/WallpaperPicker/res/values-el/strings.xml
index fc3f2a6..4b2963e 100644
--- a/WallpaperPicker/res/values-el/strings.xml
+++ b/WallpaperPicker/res/values-el/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Οι φωτογραφίες μου"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Ταπετσαρίες"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Περικοπή ταπετσαρίας"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-en-rAU/strings.xml b/WallpaperPicker/res/values-en-rAU/strings.xml
index 006746e..d9b9cb1 100644
--- a/WallpaperPicker/res/values-en-rAU/strings.xml
+++ b/WallpaperPicker/res/values-en-rAU/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"Home screen"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"Lock screen"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"Home screen and lock screen"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-en-rGB/strings.xml b/WallpaperPicker/res/values-en-rGB/strings.xml
index 006746e..d9b9cb1 100644
--- a/WallpaperPicker/res/values-en-rGB/strings.xml
+++ b/WallpaperPicker/res/values-en-rGB/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"Home screen"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"Lock screen"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"Home screen and lock screen"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-en-rIN/strings.xml b/WallpaperPicker/res/values-en-rIN/strings.xml
index 006746e..d9b9cb1 100644
--- a/WallpaperPicker/res/values-en-rIN/strings.xml
+++ b/WallpaperPicker/res/values-en-rIN/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"Home screen"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"Lock screen"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"Home screen and lock screen"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-es-rUS/strings.xml b/WallpaperPicker/res/values-es-rUS/strings.xml
index 7362b7b..cb62513 100644
--- a/WallpaperPicker/res/values-es-rUS/strings.xml
+++ b/WallpaperPicker/res/values-es-rUS/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mis fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-es/strings.xml b/WallpaperPicker/res/values-es/strings.xml
index 3c88ec6..121b392 100644
--- a/WallpaperPicker/res/values-es/strings.xml
+++ b/WallpaperPicker/res/values-es/strings.xml
@@ -29,8 +29,14 @@
     </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">"Quitar"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
     <string name="pick_image" msgid="3189640419551368385">"Mis fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-et-rEE/strings.xml b/WallpaperPicker/res/values-et-rEE/strings.xml
index 541b1d4..53be957 100644
--- a/WallpaperPicker/res/values-et-rEE/strings.xml
+++ b/WallpaperPicker/res/values-et-rEE/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Minu fotod"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Taustapildid"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Taustapildi kärpimine"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-eu-rES/strings.xml b/WallpaperPicker/res/values-eu-rES/strings.xml
index 5e627f0..8eb490c 100644
--- a/WallpaperPicker/res/values-eu-rES/strings.xml
+++ b/WallpaperPicker/res/values-eu-rES/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Nire argazkiak"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Horma-paperak"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Ebaki horma-papera"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-fa/strings.xml b/WallpaperPicker/res/values-fa/strings.xml
index 8c57117..9764e9a 100644
--- a/WallpaperPicker/res/values-fa/strings.xml
+++ b/WallpaperPicker/res/values-fa/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"عکس‌های من"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"کاغذدیواری‌ها"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"برش کاغذدیواری"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-fi/strings.xml b/WallpaperPicker/res/values-fi/strings.xml
index d1d7c27..7d5a30a 100644
--- a/WallpaperPicker/res/values-fi/strings.xml
+++ b/WallpaperPicker/res/values-fi/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Omat valokuvat"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Taustakuvat"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Rajaa taustakuva"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-fr-rCA/strings.xml b/WallpaperPicker/res/values-fr-rCA/strings.xml
index 0eea5ea..78ed165 100644
--- a/WallpaperPicker/res/values-fr-rCA/strings.xml
+++ b/WallpaperPicker/res/values-fr-rCA/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mes photos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Rogner le fond d\'écran"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-fr/strings.xml b/WallpaperPicker/res/values-fr/strings.xml
index 3775fcc..8a3ba67 100644
--- a/WallpaperPicker/res/values-fr/strings.xml
+++ b/WallpaperPicker/res/values-fr/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mes photos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Recadrer le fond d\'écran"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-gl-rES/strings.xml b/WallpaperPicker/res/values-gl-rES/strings.xml
index 3360a61..4ac52c6 100644
--- a/WallpaperPicker/res/values-gl-rES/strings.xml
+++ b/WallpaperPicker/res/values-gl-rES/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"As miñas fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-gu-rIN/strings.xml b/WallpaperPicker/res/values-gu-rIN/strings.xml
index 9783c60..48fc6e8 100644
--- a/WallpaperPicker/res/values-gu-rIN/strings.xml
+++ b/WallpaperPicker/res/values-gu-rIN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"મારા ફોટા"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"વૉલપેપર્સ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"વૉલપેપર કાપો"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-hi/strings.xml b/WallpaperPicker/res/values-hi/strings.xml
index a3a0b10..5b2cd62 100644
--- a/WallpaperPicker/res/values-hi/strings.xml
+++ b/WallpaperPicker/res/values-hi/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"मेरी फ़ोटो"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"वॉलपेपर"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"वॉलपेपर काटें"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-hr/strings.xml b/WallpaperPicker/res/values-hr/strings.xml
index 4cc800f..fa98cfa 100644
--- a/WallpaperPicker/res/values-hr/strings.xml
+++ b/WallpaperPicker/res/values-hr/strings.xml
@@ -34,4 +34,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Pozadine"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Obrezivanje pozadinske slike"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-hu/strings.xml b/WallpaperPicker/res/values-hu/strings.xml
index 6a0c91d..bb59ee3 100644
--- a/WallpaperPicker/res/values-hu/strings.xml
+++ b/WallpaperPicker/res/values-hu/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Saját fotók"</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>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-hy-rAM/strings.xml b/WallpaperPicker/res/values-hy-rAM/strings.xml
index f04ad52..8d011c3 100644
--- a/WallpaperPicker/res/values-hy-rAM/strings.xml
+++ b/WallpaperPicker/res/values-hy-rAM/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Իմ լուսանկարները"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Պաստառներ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Եզրատել պաստառը"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-in/strings.xml b/WallpaperPicker/res/values-in/strings.xml
index 96f90c0..990a235 100644
--- a/WallpaperPicker/res/values-in/strings.xml
+++ b/WallpaperPicker/res/values-in/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Foto saya"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Wallpaper"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas wallpaper"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-is-rIS/strings.xml b/WallpaperPicker/res/values-is-rIS/strings.xml
index a643273..9c1db9f 100644
--- a/WallpaperPicker/res/values-is-rIS/strings.xml
+++ b/WallpaperPicker/res/values-is-rIS/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Myndirnar mínar"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Veggfóður"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Skera veggfóður"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-it/strings.xml b/WallpaperPicker/res/values-it/strings.xml
index 7ddf655..91430dd 100644
--- a/WallpaperPicker/res/values-it/strings.xml
+++ b/WallpaperPicker/res/values-it/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Le mie foto"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Sfondi"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Ritaglia sfondo"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-iw/strings.xml b/WallpaperPicker/res/values-iw/strings.xml
index 97d3ad1..72ad4c2 100644
--- a/WallpaperPicker/res/values-iw/strings.xml
+++ b/WallpaperPicker/res/values-iw/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"התמונות שלי"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"טפטים"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"חתוך את הטפט"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ja/strings.xml b/WallpaperPicker/res/values-ja/strings.xml
index bdda7b9..39e8270 100644
--- a/WallpaperPicker/res/values-ja/strings.xml
+++ b/WallpaperPicker/res/values-ja/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"マイフォト"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"壁紙"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"壁紙のトリミング"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ka-rGE/strings.xml b/WallpaperPicker/res/values-ka-rGE/strings.xml
index 5546330..1cc78cd 100644
--- a/WallpaperPicker/res/values-ka-rGE/strings.xml
+++ b/WallpaperPicker/res/values-ka-rGE/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"ჩემი ფოტოები"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ფონები"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ფონის ჩამოჭრა"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-kk-rKZ/strings.xml b/WallpaperPicker/res/values-kk-rKZ/strings.xml
index 31332c5..c78a8d8 100644
--- a/WallpaperPicker/res/values-kk-rKZ/strings.xml
+++ b/WallpaperPicker/res/values-kk-rKZ/strings.xml
@@ -31,6 +31,12 @@
     <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="3189640419551368385">"Менің фотосуреттерім"</string>
-    <string name="pick_wallpaper" msgid="4628969645948454559">"Тұсқағаздар"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Артқы фондар"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Артқы фонды кесу"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-km-rKH/strings.xml b/WallpaperPicker/res/values-km-rKH/strings.xml
index 3e72ac8..402f28e 100644
--- a/WallpaperPicker/res/values-km-rKH/strings.xml
+++ b/WallpaperPicker/res/values-km-rKH/strings.xml
@@ -30,7 +30,13 @@
     <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="3189640419551368385">"រូបថតខ្ញុំ"</string>
+    <string name="pick_image" msgid="3189640419551368385">"រូបថតរបស់ខ្ញុំ"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ផ្ទាំង​រូបភាព"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ច្រឹប​ផ្ទាំង​រូបភាព"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-kn-rIN/strings.xml b/WallpaperPicker/res/values-kn-rIN/strings.xml
index 4946cb4..1b467f4 100644
--- a/WallpaperPicker/res/values-kn-rIN/strings.xml
+++ b/WallpaperPicker/res/values-kn-rIN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"ನನ್ನ ಫೋಟೋಗಳು"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ವಾಲ್‌ಪೇಪರ್‌ ಕತ್ತರಿಸಿ"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ko/strings.xml b/WallpaperPicker/res/values-ko/strings.xml
index 81d6a38..7da91da 100644
--- a/WallpaperPicker/res/values-ko/strings.xml
+++ b/WallpaperPicker/res/values-ko/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"내 사진"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"배경화면"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"배경화면 잘라내기"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"메인 스크린"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"잠금 화면"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"메인 스크린 및 잠금 화면"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-ky-rKG/strings.xml b/WallpaperPicker/res/values-ky-rKG/strings.xml
index 4a65a05..acf8b5d 100644
--- a/WallpaperPicker/res/values-ky-rKG/strings.xml
+++ b/WallpaperPicker/res/values-ky-rKG/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Менин сүрөттөрүм"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Тушкагаздар"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Тушкагазды тегиздөө"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-lo-rLA/strings.xml b/WallpaperPicker/res/values-lo-rLA/strings.xml
index 1dc2d11..f6bfa1e 100644
--- a/WallpaperPicker/res/values-lo-rLA/strings.xml
+++ b/WallpaperPicker/res/values-lo-rLA/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"ຮູບຂອງຂ້ອຍ"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ພາບພື້ນຫຼັງ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ຕັດພາບພື້ນຫຼັງ"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"ໜ້າຈໍຫຼັກ"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"ໜ້າຈໍລັອກ"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"ໜ້າຈໍຫຼັກ ແລະ ໜ້າຈໍລັອກ"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-lt/strings.xml b/WallpaperPicker/res/values-lt/strings.xml
index 4ecd092..f9127d8 100644
--- a/WallpaperPicker/res/values-lt/strings.xml
+++ b/WallpaperPicker/res/values-lt/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mano nuotraukos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Ekrano fonai"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Apkirpti ekrano foną"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-lv/strings.xml b/WallpaperPicker/res/values-lv/strings.xml
index e271705..d8601dc 100644
--- a/WallpaperPicker/res/values-lv/strings.xml
+++ b/WallpaperPicker/res/values-lv/strings.xml
@@ -34,4 +34,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mani fotoattēli"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fona tapetes"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Apgriezt fona tapeti"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-mk-rMK/strings.xml b/WallpaperPicker/res/values-mk-rMK/strings.xml
index 1855ee3..c881595 100644
--- a/WallpaperPicker/res/values-mk-rMK/strings.xml
+++ b/WallpaperPicker/res/values-mk-rMK/strings.xml
@@ -19,7 +19,7 @@
 
 <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="wallpaper_instructions" msgid="3524143401182707094">"Подеси тапет"</string>
     <string name="image_load_fail" msgid="7538534580694411837">"Сликата не можеше да се вчита"</string>
     <string name="wallpaper_load_fail" msgid="4800700444605404650">"Сликата не можеше да се вчита како тапет"</string>
     <string name="wallpaper_set_fail" msgid="7023180794008631780">"Сликата не може да се постави како тапет"</string>
@@ -31,6 +31,12 @@
     <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="3189640419551368385">"Моите фотографии"</string>
-    <string name="pick_wallpaper" msgid="4628969645948454559">"Позадини"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Тапети"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Исечи тапет"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ml-rIN/strings.xml b/WallpaperPicker/res/values-ml-rIN/strings.xml
index 2ecfae8..35eb6c0 100644
--- a/WallpaperPicker/res/values-ml-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ml-rIN/strings.xml
@@ -31,6 +31,12 @@
     <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="3189640419551368385">"എന്റെ ഫോട്ടോകൾ"</string>
-    <string name="pick_wallpaper" msgid="4628969645948454559">"വാൾപേപ്പർ"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"വാൾപേപ്പറുകൾ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"വാൾപേപ്പറിന്റെ വലുപ്പം മാറ്റൽ"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-mn-rMN/strings.xml b/WallpaperPicker/res/values-mn-rMN/strings.xml
index 539bc0d..ca55055 100644
--- a/WallpaperPicker/res/values-mn-rMN/strings.xml
+++ b/WallpaperPicker/res/values-mn-rMN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Миний зураг"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Ханын зураг"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Ханын зургийг тайрах"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-mr-rIN/strings.xml b/WallpaperPicker/res/values-mr-rIN/strings.xml
index 97fe621..3d76d20 100644
--- a/WallpaperPicker/res/values-mr-rIN/strings.xml
+++ b/WallpaperPicker/res/values-mr-rIN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"माझे फोटो"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"वॉलपेपर"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"वॉलपेपर कापा"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ms-rMY/strings.xml b/WallpaperPicker/res/values-ms-rMY/strings.xml
index 4a08261..a60ba06 100644
--- a/WallpaperPicker/res/values-ms-rMY/strings.xml
+++ b/WallpaperPicker/res/values-ms-rMY/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Foto saya"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Kertas dinding"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas kertas dinding"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-my-rMM/strings.xml b/WallpaperPicker/res/values-my-rMM/strings.xml
index 19527d8..32d92fa 100644
--- a/WallpaperPicker/res/values-my-rMM/strings.xml
+++ b/WallpaperPicker/res/values-my-rMM/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"ကျွန်ုပ်၏ ဓာတ်ပုံများ"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"နောက်ခံများ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"နောက်ခံအား ဖြတ်ခြင်း"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-nb/strings.xml b/WallpaperPicker/res/values-nb/strings.xml
index 668ed81..d9ce246 100644
--- a/WallpaperPicker/res/values-nb/strings.xml
+++ b/WallpaperPicker/res/values-nb/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mine bilder"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunner"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Beskjær bakgrunnen"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ne-rNP/strings.xml b/WallpaperPicker/res/values-ne-rNP/strings.xml
index 63e6c06..fca4886 100644
--- a/WallpaperPicker/res/values-ne-rNP/strings.xml
+++ b/WallpaperPicker/res/values-ne-rNP/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"मेरा तस्बिरहरू"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"वालपेपरहरु"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"वालपेपर काँटछाट गर्नुहोस्"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"गृह स्क्रिन"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"लक स्क्रिन"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"गृह स्क्रिन र लक स्क्रिन"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-nl/strings.xml b/WallpaperPicker/res/values-nl/strings.xml
index a245fbf..7246b22 100644
--- a/WallpaperPicker/res/values-nl/strings.xml
+++ b/WallpaperPicker/res/values-nl/strings.xml
@@ -31,6 +31,12 @@
     <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="3189640419551368385">"Mijn foto\'s"</string>
-    <string name="pick_wallpaper" msgid="4628969645948454559">"Achtergrond"</string>
+    <string name="pick_wallpaper" msgid="4628969645948454559">"Achtergronden"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Achtergrond bijsnijden"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-pa-rIN/strings.xml b/WallpaperPicker/res/values-pa-rIN/strings.xml
index 36a6059..3532fcb 100644
--- a/WallpaperPicker/res/values-pa-rIN/strings.xml
+++ b/WallpaperPicker/res/values-pa-rIN/strings.xml
@@ -19,7 +19,7 @@
 
 <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="wallpaper_instructions" msgid="3524143401182707094">"ਵਾਲਪੇਪਰ ਸੈਟ ਕਰੋ"</string>
     <string name="image_load_fail" msgid="7538534580694411837">"ਚਿੱਤਰ ਲੋਡ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
     <string name="wallpaper_load_fail" msgid="4800700444605404650">"ਵਾਲਪੇਪਰ ਦੇ ਤੌਰ ਤੇ ਚਿੱਤਰ ਲੋਡ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
     <string name="wallpaper_set_fail" msgid="7023180794008631780">"ਵਾਲਪੇਪਰ ਦੇ ਤੌਰ ਤੇ ਚਿੱਤਰ ਸੈਟ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"ਮੇਰੀਆਂ ਫੋਟੋਆਂ"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"ਵਾਲਪੇਪਰ"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ਵਾਲਪੇਪਰ ਕੱਟੋ"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-pl/strings.xml b/WallpaperPicker/res/values-pl/strings.xml
index e5754f6..9815363 100644
--- a/WallpaperPicker/res/values-pl/strings.xml
+++ b/WallpaperPicker/res/values-pl/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Moje zdjęcia"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Przytnij tapetę"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-pt-rPT/strings.xml b/WallpaperPicker/res/values-pt-rPT/strings.xml
index aa1463f..f64815e 100644
--- a/WallpaperPicker/res/values-pt-rPT/strings.xml
+++ b/WallpaperPicker/res/values-pt-rPT/strings.xml
@@ -19,7 +19,7 @@
 
 <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 de fundo"</string>
+    <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>
     <string name="wallpaper_set_fail" msgid="7023180794008631780">"Não foi possível definir a imagem como imagem de fundo"</string>
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"As minhas fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Imagens de fundo"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Recortar imagem de fundo"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-pt/strings.xml b/WallpaperPicker/res/values-pt/strings.xml
index 29e0384..be573ae 100644
--- a/WallpaperPicker/res/values-pt/strings.xml
+++ b/WallpaperPicker/res/values-pt/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Minhas fotos"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Planos de fundo"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Cortar plano de fundo"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ro/strings.xml b/WallpaperPicker/res/values-ro/strings.xml
index f791887..7594bf7 100644
--- a/WallpaperPicker/res/values-ro/strings.xml
+++ b/WallpaperPicker/res/values-ro/strings.xml
@@ -34,4 +34,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Fotografiile mele"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Imagini de fundal"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Decupați imaginea de fundal"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ru/strings.xml b/WallpaperPicker/res/values-ru/strings.xml
index 9ea1e88..e8e9972 100644
--- a/WallpaperPicker/res/values-ru/strings.xml
+++ b/WallpaperPicker/res/values-ru/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Мои фото"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Обои"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Кадрировать обои"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-si-rLK/strings.xml b/WallpaperPicker/res/values-si-rLK/strings.xml
index 5cdbcb9..ca85089 100644
--- a/WallpaperPicker/res/values-si-rLK/strings.xml
+++ b/WallpaperPicker/res/values-si-rLK/strings.xml
@@ -35,4 +35,7 @@
     <string name="pick_image" msgid="3189640419551368385">"මගේ ඡායාරූප"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"වෝල්පේපර"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"වෝල්පේපරය කප්පාදු කිරීම"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"මුල් පිටු තිරය"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"අගුලු තිරය"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"මුල් පිටු තිරය සහ අගුලු තිරය"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-sk/strings.xml b/WallpaperPicker/res/values-sk/strings.xml
index 458448d..69aa6f9 100644
--- a/WallpaperPicker/res/values-sk/strings.xml
+++ b/WallpaperPicker/res/values-sk/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Moje fotky"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Orezanie tapety"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-sl/strings.xml b/WallpaperPicker/res/values-sl/strings.xml
index dbeb53a..43dea98 100644
--- a/WallpaperPicker/res/values-sl/strings.xml
+++ b/WallpaperPicker/res/values-sl/strings.xml
@@ -35,4 +35,7 @@
     <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Ozadja"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Obrezovanje ozadja"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"Začetni zaslon"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"Zaklenjen zaslon"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"Začetni zaslon in zaklenjen zaslon"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-sq-rAL/strings.xml b/WallpaperPicker/res/values-sq-rAL/strings.xml
index 96ad16b..c3cac5b 100644
--- a/WallpaperPicker/res/values-sq-rAL/strings.xml
+++ b/WallpaperPicker/res/values-sq-rAL/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Fotografitë e mia"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Imazhet e sfondit"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Prit imazhin e sfondit"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-sr/strings.xml b/WallpaperPicker/res/values-sr/strings.xml
index edab2dc..28dfd92 100644
--- a/WallpaperPicker/res/values-sr/strings.xml
+++ b/WallpaperPicker/res/values-sr/strings.xml
@@ -31,7 +31,13 @@
     <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="3189640419551368385">"Моје слике"</string>
+    <string name="pick_image" msgid="3189640419551368385">"Моје фотографије"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Позадине"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Опсеци позадину"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-sv/strings.xml b/WallpaperPicker/res/values-sv/strings.xml
index 7f6faa3..32c0a5a 100644
--- a/WallpaperPicker/res/values-sv/strings.xml
+++ b/WallpaperPicker/res/values-sv/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mina foton"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunder"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Beskär bakgrund"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-sw/strings.xml b/WallpaperPicker/res/values-sw/strings.xml
index ab4fe5c..3294321 100644
--- a/WallpaperPicker/res/values-sw/strings.xml
+++ b/WallpaperPicker/res/values-sw/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Picha zangu"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Mandhari"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Punguza mandhari"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ta-rIN/strings.xml b/WallpaperPicker/res/values-ta-rIN/strings.xml
index f856c94..5528072 100644
--- a/WallpaperPicker/res/values-ta-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ta-rIN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"எனது படங்கள்"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"வால்பேப்பர்கள்"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"வால்பேப்பரைச் செதுக்கு"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-te-rIN/strings.xml b/WallpaperPicker/res/values-te-rIN/strings.xml
index 7ca48aa..0c9e9eb 100644
--- a/WallpaperPicker/res/values-te-rIN/strings.xml
+++ b/WallpaperPicker/res/values-te-rIN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"నా ఫోటోలు"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"వాల్‌పేపర్‌లు"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"వాల్‌పేపర్‌ను కత్తిరించండి"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-th/strings.xml b/WallpaperPicker/res/values-th/strings.xml
index 2616d01..48aee2a 100644
--- a/WallpaperPicker/res/values-th/strings.xml
+++ b/WallpaperPicker/res/values-th/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"รูปภาพของฉัน"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"วอลเปเปอร์"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"ครอบตัดวอลเปเปอร์"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-tl/strings.xml b/WallpaperPicker/res/values-tl/strings.xml
index 64f678d..14bf572 100644
--- a/WallpaperPicker/res/values-tl/strings.xml
+++ b/WallpaperPicker/res/values-tl/strings.xml
@@ -29,8 +29,14 @@
     </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">"I-delete"</string>
+    <string name="wallpaper_delete" msgid="1459353972739215344">"Tanggalin"</string>
     <string name="pick_image" msgid="3189640419551368385">"Aking mga larawan"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Mga Wallpaper"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"I-crop ang wallpaper"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-tr/strings.xml b/WallpaperPicker/res/values-tr/strings.xml
index 2488a07..82c6ef8 100644
--- a/WallpaperPicker/res/values-tr/strings.xml
+++ b/WallpaperPicker/res/values-tr/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Fotoğraflarım"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Duvar kağıtları"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Duvar kağıdını kırp"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-uk/strings.xml b/WallpaperPicker/res/values-uk/strings.xml
index 84f180f..b59409a 100644
--- a/WallpaperPicker/res/values-uk/strings.xml
+++ b/WallpaperPicker/res/values-uk/strings.xml
@@ -35,4 +35,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Мої фото"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Фонові малюнки"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Обрізати фоновий малюнок"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-ur-rPK/strings.xml b/WallpaperPicker/res/values-ur-rPK/strings.xml
index 703fabc..616b36f 100644
--- a/WallpaperPicker/res/values-ur-rPK/strings.xml
+++ b/WallpaperPicker/res/values-ur-rPK/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"میری تصاویر"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"وال پیپرز"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"وال پیپر کو تراشیں"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-uz-rUZ/strings.xml b/WallpaperPicker/res/values-uz-rUZ/strings.xml
index 7ffb1c4..45c9e98 100644
--- a/WallpaperPicker/res/values-uz-rUZ/strings.xml
+++ b/WallpaperPicker/res/values-uz-rUZ/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Mening rasmlarim"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Fon rasmlari"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Fon rasmini kesish"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-vi/strings.xml b/WallpaperPicker/res/values-vi/strings.xml
index 01c18f4..5aafc06 100644
--- a/WallpaperPicker/res/values-vi/strings.xml
+++ b/WallpaperPicker/res/values-vi/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Ảnh của tôi"</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>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-zh-rCN/strings.xml b/WallpaperPicker/res/values-zh-rCN/strings.xml
index 3369cff..9b9b509 100644
--- a/WallpaperPicker/res/values-zh-rCN/strings.xml
+++ b/WallpaperPicker/res/values-zh-rCN/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"我的照片"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"壁纸"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"剪裁壁纸"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-zh-rHK/strings.xml b/WallpaperPicker/res/values-zh-rHK/strings.xml
index bc09d58..c3c2271 100644
--- a/WallpaperPicker/res/values-zh-rHK/strings.xml
+++ b/WallpaperPicker/res/values-zh-rHK/strings.xml
@@ -33,4 +33,7 @@
     <string name="pick_image" msgid="3189640419551368385">"我的相片"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
+    <string name="which_wallpaper_option_home_screen" msgid="5259213374485080595">"主畫面"</string>
+    <string name="which_wallpaper_option_lock_screen" msgid="5474588303389139825">"上鎖畫面"</string>
+    <string name="which_wallpaper_option_home_screen_and_lock_screen" msgid="7652312651094808607">"主畫面和上鎖畫面"</string>
 </resources>
diff --git a/WallpaperPicker/res/values-zh-rTW/strings.xml b/WallpaperPicker/res/values-zh-rTW/strings.xml
index 90f9fac..b22c691 100644
--- a/WallpaperPicker/res/values-zh-rTW/strings.xml
+++ b/WallpaperPicker/res/values-zh-rTW/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"我的相片"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/WallpaperPicker/res/values-zu/strings.xml b/WallpaperPicker/res/values-zu/strings.xml
index ba43741..0069293 100644
--- a/WallpaperPicker/res/values-zu/strings.xml
+++ b/WallpaperPicker/res/values-zu/strings.xml
@@ -33,4 +33,10 @@
     <string name="pick_image" msgid="3189640419551368385">"Izithombe zami"</string>
     <string name="pick_wallpaper" msgid="4628969645948454559">"Izithombe zangemuva"</string>
     <string name="crop_wallpaper" msgid="4882870800623585836">"Nqampuna isithombe sangemuva"</string>
+    <!-- no translation found for which_wallpaper_option_home_screen (5259213374485080595) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_lock_screen (5474588303389139825) -->
+    <skip />
+    <!-- no translation found for which_wallpaper_option_home_screen_and_lock_screen (7652312651094808607) -->
+    <skip />
 </resources>
diff --git a/res/layout/launcher_overlay.xml b/WallpaperPicker/res/values/arrays.xml
similarity index 62%
rename from res/layout/launcher_overlay.xml
rename to WallpaperPicker/res/values/arrays.xml
index b35a2d8..5c10b98 100644
--- a/res/layout/launcher_overlay.xml
+++ b/WallpaperPicker/res/values/arrays.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,8 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<com.android.launcher3.InsettableFrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" />
+<resources>
+    <string-array name="which_wallpaper_options">
+        <item>@string/which_wallpaper_option_home_screen</item>
+        <item>@string/which_wallpaper_option_lock_screen</item>
+        <item>@string/which_wallpaper_option_home_screen_and_lock_screen</item>
+    </string-array>
+</resources>
\ No newline at end of file
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
index 2bfd476..aef6a1a 100644
--- a/WallpaperPicker/res/values/strings.xml
+++ b/WallpaperPicker/res/values/strings.xml
@@ -53,4 +53,11 @@
     <string name="pick_wallpaper">Wallpapers</string>
     <!-- Title of activity for cropping wallpapers -->
     <string name="crop_wallpaper">Crop wallpaper</string>
+
+    <!-- Option for setting the wallpaper only on the home screen. -->
+    <string name="which_wallpaper_option_home_screen">Home screen</string>
+    <!-- Option for setting the wallpaper only on the lock screen. -->
+    <string name="which_wallpaper_option_lock_screen">Lock screen</string>
+    <!-- Option for setting the wallpaper on both the home screen and lock screen. -->
+    <string name="which_wallpaper_option_home_screen_and_lock_screen">Home screen and lock screen</string>
 </resources>
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
index 8b51447..153fa90 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
@@ -33,7 +33,9 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.launcher3.NycWallpaperUtils;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
@@ -42,10 +44,10 @@
 import java.io.IOException;
 import java.io.InputStream;
 
-public class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
+public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
 
     public interface OnBitmapCroppedHandler {
-        public void onBitmapCropped(byte[] imageBytes);
+        public void onBitmapCropped(byte[] imageBytes, Rect cropHint);
     }
 
     public interface OnEndCropHandler {
@@ -71,15 +73,6 @@
     BitmapCropTask.OnBitmapCroppedHandler mOnBitmapCroppedHandler;
     boolean mNoCrop;
 
-    public BitmapCropTask(Context c, String filePath,
-            RectF cropBounds, int rotation, int outWidth, int outHeight,
-            boolean setWallpaper, boolean saveCroppedBitmap, OnEndCropHandler onEndCropHandler) {
-        mContext = c;
-        mInFilePath = filePath;
-        init(cropBounds, rotation,
-                outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndCropHandler);
-    }
-
     public BitmapCropTask(byte[] imageBytes,
             RectF cropBounds, int rotation, int outWidth, int outHeight,
             boolean setWallpaper, boolean saveCroppedBitmap, OnEndCropHandler onEndCropHandler) {
@@ -175,28 +168,45 @@
     public Bitmap getCroppedBitmap() {
         return mCroppedBitmap;
     }
-    public boolean cropBitmap() {
+    public boolean cropBitmap(int whichWallpaper) {
         boolean failure = false;
 
-
-        WallpaperManager wallpaperManager = null;
-        if (mSetWallpaper) {
-            wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
-        }
-
-
         if (mSetWallpaper && mNoCrop) {
             try {
                 InputStream is = regenerateInputStream();
-                if (is != null) {
-                    wallpaperManager.setStream(is);
-                    Utils.closeSilently(is);
-                }
+                setWallpaper(is, null, whichWallpaper);
+                Utils.closeSilently(is);
             } catch (IOException e) {
                 Log.w(LOGTAG, "cannot write stream to wallpaper", e);
                 failure = true;
             }
             return !failure;
+        } else if (mSetWallpaper && Utilities.isNycOrAbove()
+                && mRotation == 0 && mOutWidth > 0 && mOutHeight > 0) {
+            Rect hint = new Rect();
+            mCropBounds.roundOut(hint);
+
+            InputStream is = null;
+            try {
+                is = regenerateInputStream();
+                if (is == null) {
+                    Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
+                    failure = true;
+                    return false;
+                }
+                WallpaperManager.getInstance(mContext).suggestDesiredDimensions(mOutWidth, mOutHeight);
+                setWallpaper(is, hint, whichWallpaper);
+
+                if (mOnBitmapCroppedHandler != null) {
+                    mOnBitmapCroppedHandler.onBitmapCropped(null, hint);
+                }
+
+                failure = false;
+            } catch (IOException e) {
+                Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+            } finally {
+                Utils.closeSilently(is);
+            }
         } else {
             // Find crop bounds (scaled to original image size)
             Rect roundedTrueCrop = new Rect();
@@ -225,7 +235,6 @@
                 mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
                 inverseRotateMatrix.mapRect(mCropBounds);
                 mCropBounds.offset(bounds.x/2, bounds.y/2);
-
             }
 
             mCropBounds.roundOut(roundedTrueCrop);
@@ -372,12 +381,13 @@
             ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
             if (crop.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
                 // If we need to set to the wallpaper, set it
-                if (mSetWallpaper && wallpaperManager != null) {
+                if (mSetWallpaper) {
                     try {
                         byte[] outByteArray = tmpOut.toByteArray();
-                        wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
+                        setWallpaper(new ByteArrayInputStream(outByteArray), null, whichWallpaper);
                         if (mOnBitmapCroppedHandler != null) {
-                            mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
+                            mOnBitmapCroppedHandler.onBitmapCropped(outByteArray,
+                                    new Rect(0, 0, crop.getWidth(), crop.getHeight()));
                         }
                     } catch (IOException e) {
                         Log.w(LOGTAG, "cannot write stream to wallpaper", e);
@@ -393,8 +403,8 @@
     }
 
     @Override
-    protected Boolean doInBackground(Void... params) {
-        return cropBitmap();
+    protected Boolean doInBackground(Integer... params) {
+        return cropBitmap(params.length == 0 ? NycWallpaperUtils.FLAG_SET_SYSTEM : params[0]);
     }
 
     @Override
@@ -406,4 +416,12 @@
             mOnEndCropHandler.run(cropSucceeded);
         }
     }
+
+    private void setWallpaper(InputStream in, Rect crop, int whichWallpaper) throws IOException {
+        if (!Utilities.isNycOrAbove()) {
+            WallpaperManager.getInstance(mContext.getApplicationContext()).setStream(in);
+        } else {
+            NycWallpaperUtils.setStream(mContext, in, crop, true, whichWallpaper);
+        }
+    }
 }
\ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java
index e98e23e..c1578c1 100644
--- a/WallpaperPicker/src/com/android/launcher3/CropView.java
+++ b/WallpaperPicker/src/com/android/launcher3/CropView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
@@ -148,12 +149,19 @@
         updateMinScale(w, h, mRenderer.source, false);
     }
 
-    public void setScale(float scale) {
+    public void setScaleAndCenter(float scale, float x, float y) {
         synchronized (mLock) {
             mRenderer.scale = scale;
+            mCenterX = x;
+            mCenterY = y;
+            updateCenter();
         }
     }
 
+    public float getScale() {
+        return mRenderer.scale;
+    }
+
     private void updateMinScale(int w, int h, TileSource source, boolean resetScale) {
         synchronized (mLock) {
             if (resetScale) {
@@ -189,17 +197,6 @@
     public void onScaleEnd(ScaleGestureDetector detector) {
     }
 
-    /**
-     * Offsets wallpaper preview according to the state it will be displayed in upon returning home.
-     * @param offset Ranges from 0 to 1, where 0 is the leftmost parallax and 1 is the rightmost.
-     */
-    public void setParallaxOffset(float offset, RectF crop) {
-        offset = Math.max(0, Math.min(offset, 1)); // Make sure the offset is in the correct range.
-        float screenWidth = getWidth() / mRenderer.scale;
-        mCenterX = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
-        updateCenter();
-    }
-
     public void moveToLeft() {
         if (getWidth() == 0 || getHeight() == 0) {
             final ViewTreeObserver observer = getViewTreeObserver();
@@ -222,6 +219,10 @@
         mRenderer.centerY = Math.round(mCenterY);
     }
 
+    public PointF getCenter() {
+        return new PointF(mCenterX, mCenterY);
+    }
+
     public void setTouchEnabled(boolean enabled) {
         mTouchEnabled = enabled;
     }
diff --git a/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java b/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java
new file mode 100644
index 0000000..abac830
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java
@@ -0,0 +1,79 @@
+package com.android.launcher3;
+
+import android.app.AlertDialog;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Utility class used to help set lockscreen wallpapers on N+.
+ */
+public class NycWallpaperUtils {
+    public static final int FLAG_SET_SYSTEM = 1 << 0; // TODO: use WallpaperManager.FLAG_SET_SYSTEM
+    public static final int FLAG_SET_LOCK = 1 << 1; // TODO: use WallpaperManager.FLAG_SET_LOCK
+
+    /**
+     * Calls cropTask.execute(), once the user has selected which wallpaper to set. On pre-N
+     * devices, the prompt is not displayed since there is no API to set the lockscreen wallpaper.
+     */
+    public static void executeCropTaskAfterPrompt(
+            Context context, final AsyncTask<Integer, ?, ?> cropTask,
+            DialogInterface.OnCancelListener onCancelListener) {
+        if (Utilities.isNycOrAbove()) {
+            new AlertDialog.Builder(context)
+                    .setTitle(R.string.wallpaper_instructions)
+                    .setItems(R.array.which_wallpaper_options, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int selectedItemIndex) {
+                            int whichWallpaper;
+                            if (selectedItemIndex == 0) {
+                                whichWallpaper = FLAG_SET_SYSTEM;
+                            } else if (selectedItemIndex == 1) {
+                                whichWallpaper = FLAG_SET_LOCK;
+                            } else {
+                                whichWallpaper = FLAG_SET_SYSTEM | FLAG_SET_LOCK;
+                            }
+                            cropTask.execute(whichWallpaper);
+                        }
+                    })
+                    .setOnCancelListener(onCancelListener)
+                    .show();
+        } else {
+            cropTask.execute(FLAG_SET_SYSTEM);
+        }
+    }
+
+    public static void setStream(Context context, final InputStream data, Rect visibleCropHint,
+            boolean allowBackup, int whichWallpaper) throws IOException {
+        WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
+        try {
+            // TODO: use mWallpaperManager.setStream(data, visibleCropHint, allowBackup, which)
+            // without needing reflection.
+            Method setStream = WallpaperManager.class.getMethod("setStream", InputStream.class,
+                    Rect.class, boolean.class, int.class);
+            setStream.invoke(wallpaperManager, data, visibleCropHint, allowBackup, whichWallpaper);
+        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+            // Fall back to previous implementation (set system)
+            wallpaperManager.setStream(data);
+        }
+    }
+
+    public static void clear(Context context, int whichWallpaper) throws IOException {
+        WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
+        try {
+            // TODO: use mWallpaperManager.clear(whichWallpaper) without needing reflection.
+            Method clear = WallpaperManager.class.getMethod("clear", int.class);
+            clear.invoke(wallpaperManager, whichWallpaper);
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            // Fall back to previous implementation (clear system)
+            wallpaperManager.clear();
+        }
+    }
+}
\ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index 64b0ac4..34226f7 100644
--- a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
+++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
@@ -25,6 +25,8 @@
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -33,9 +35,14 @@
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
+import com.android.launcher3.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
+import com.android.photos.views.TiledImageRenderer.TileSource;
+
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 
 
@@ -48,15 +55,42 @@
 
     public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
         private int mDbId;
-        public SavedWallpaperTile(int dbId, File target, Drawable thumb) {
+
+        // three floats representing scale, centerX and centerY of the crop view in order.
+        private Float[] mExtras;
+        public SavedWallpaperTile(int dbId, File target, Drawable thumb, Float[] extras) {
             super(target, thumb);
             mDbId = dbId;
+            mExtras = extras != null && extras.length == 3 ? extras : null;
         }
 
         @Override
         public void onDelete(WallpaperPickerActivity a) {
             a.getSavedImages().deleteImage(mDbId);
         }
+
+        @Override
+        protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
+            if (mExtras != null) {
+                return new CropViewScaleAndOffsetProvider() {
+                    @Override
+                    public void updateCropView(WallpaperCropActivity a, TileSource src) {
+                        a.mCropView.setScaleAndCenter(mExtras[0], mExtras[1], mExtras[2]);
+                    }
+                };
+            }
+            return null;
+        }
+
+        @Override
+        public void onSave(final WallpaperPickerActivity a) {
+            if (mExtras == null) {
+                super.onSave(a);
+            } else {
+                boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
+                a.cropImageAndSetWallpaper(Uri.fromFile(mFile), null, true, shouldFadeOutOnFinish);
+            }
+        }
     }
 
     public SavedWallpaperImages(Context context) {
@@ -74,7 +108,8 @@
         Cursor result = db.query(ImageDb.TABLE_NAME,
                 new String[] { ImageDb.COLUMN_ID,
                     ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
-                    ImageDb.COLUMN_IMAGE_FILENAME}, // cols to return
+                    ImageDb.COLUMN_IMAGE_FILENAME,
+                    ImageDb.COLUMN_EXTRAS}, // cols to return
                 null, // select query
                 null, // args to select query
                 null,
@@ -88,9 +123,25 @@
 
             Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
             if (thumb != null) {
+
+                Float[] extras = null;
+                String extraStr = result.getString(3);
+                if (extraStr != null) {
+                    String[] parts = extraStr.split(",");
+                    extras = new Float[parts.length];
+                    for (int i = 0; i < parts.length; i++) {
+                        try {
+                            extras[i] = Float.parseFloat(parts[i]);
+                        } catch (Exception e) {
+                            extras = null;
+                            break;
+                        }
+                    }
+                }
+
                 mImages.add(new SavedWallpaperTile(result.getInt(0),
                         new File(mContext.getFilesDir(), result.getString(2)),
-                        new BitmapDrawable(thumb)));
+                        new BitmapDrawable(thumb), extras));
             }
         }
         result.close();
@@ -155,34 +206,55 @@
 
     public void writeImage(Bitmap thumbnail, byte[] imageBytes) {
         try {
-            File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
-            FileOutputStream imageFileStream =
-                    mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
-            imageFileStream.write(imageBytes);
-            imageFileStream.close();
-
-            File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
-            FileOutputStream thumbFileStream =
-                    mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
-            thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
-            thumbFileStream.close();
-
-            SQLiteDatabase db = mDb.getWritableDatabase();
-            ContentValues values = new ContentValues();
-            values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
-            values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
-            db.insert(ImageDb.TABLE_NAME, null, values);
+            writeImage(thumbnail, new ByteArrayInputStream(imageBytes), null);
         } catch (IOException e) {
             Log.e(TAG, "Failed writing images to storage " + e);
         }
     }
 
+    public void writeImage(Bitmap thumbnail, Uri uri, Float[] extras) {
+        try {
+            writeImage(thumbnail, mContext.getContentResolver().openInputStream(uri), extras);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed writing images to storage " + e);
+        }
+    }
+
+    private void writeImage(Bitmap thumbnail, InputStream in, Float[] extras) throws IOException {
+        File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
+        FileOutputStream imageFileStream =
+                mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
+        byte[] buf = new byte[4096];    // 4k
+        int len;
+        while ((len = in.read(buf)) > 0) {
+            imageFileStream.write(buf, 0, len);
+        }
+        imageFileStream.close();
+        in.close();
+
+        File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
+        FileOutputStream thumbFileStream =
+                mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
+        thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
+        thumbFileStream.close();
+
+        SQLiteDatabase db = mDb.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
+        values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
+        if (extras != null) {
+            values.put(ImageDb.COLUMN_EXTRAS, TextUtils.join(",", extras));
+        }
+        db.insert(ImageDb.TABLE_NAME, null, values);
+    }
+
     static class ImageDb extends SQLiteOpenHelper {
-        final static int DB_VERSION = 1;
+        final static int DB_VERSION = 2;
         final static String TABLE_NAME = "saved_wallpaper_images";
         final static String COLUMN_ID = "id";
         final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail";
         final static String COLUMN_IMAGE_FILENAME = "image";
+        final static String COLUMN_EXTRAS = "extras";
 
         Context mContext;
 
@@ -209,15 +281,20 @@
                     COLUMN_ID + " INTEGER NOT NULL, " +
                     COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " +
                     COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " +
+                    COLUMN_EXTRAS + " TEXT, " +
                     "PRIMARY KEY (" + COLUMN_ID + " ASC) " +
                     ");");
         }
 
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            if (oldVersion != newVersion) {
+            if (oldVersion == 1) {
+                // Add extras column
+                db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_EXTRAS + " TEXT;");
+            } else if (oldVersion != newVersion) {
                 // Delete all the records; they'll be repopulated as this is a cache
                 db.execSQL("DELETE FROM " + TABLE_NAME);
+                onCreate(db);
             }
         }
     }
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 75bdb8a..f6c53ec 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -21,6 +21,7 @@
 import android.app.Activity;
 import android.app.WallpaperManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
@@ -28,6 +29,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.RectF;
 import android.net.Uri;
 import android.os.Build;
@@ -86,6 +88,18 @@
     @Thunk Set<Bitmap> mReusableBitmaps =
             Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
 
+    private final DialogInterface.OnCancelListener mOnDialogCancelListener =
+            new DialogInterface.OnCancelListener() {
+                @Override
+                public void onCancel(DialogInterface dialog) {
+                    getActionBar().show();
+                    View wallpaperStrip = findViewById(R.id.wallpaper_strip);
+                    if (wallpaperStrip != null) {
+                        wallpaperStrip.setVisibility(View.VISIBLE);
+                    }
+                }
+            };
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -242,6 +256,10 @@
         }
     }
 
+    public DialogInterface.OnCancelListener getOnDialogCancelListener() {
+        return mOnDialogCancelListener;
+    }
+
     protected void onLoadRequestComplete(LoadRequest req, boolean success) {
         mCurrentLoadRequest = null;
         if (success) {
@@ -252,13 +270,7 @@
                 mCropView.moveToLeft();
             }
             if (req.scaleAndOffsetProvider != null) {
-                TileSource src = req.result;
-                Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
-                        getResources(), getWindowManager());
-                RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
-                        wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
-                mCropView.setScale(req.scaleAndOffsetProvider.getScale(wallpaperSize, crop));
-                mCropView.setParallaxOffset(req.scaleAndOffsetProvider.getParallaxOffset(), crop);
+                req.scaleAndOffsetProvider.updateCropView(this, req.result);
             }
 
             // Free last image
@@ -326,7 +338,7 @@
         };
         cropTask.setOnEndRunnable(onEndCrop);
         cropTask.setNoCrop(true);
-        cropTask.execute();
+        NycWallpaperUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
     }
 
     protected void cropImageAndSetWallpaper(Resources res, int resId,
@@ -335,8 +347,7 @@
         // this device
         int rotation = BitmapUtils.getRotationFromExif(res, resId);
         Point inSize = mCropView.getSourceDimensions();
-        Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
-                getWindowManager());
+        Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(), getWindowManager());
         RectF crop = Utils.getMaxCropRect(
                 inSize.x, inSize.y, outSize.x, outSize.y, false);
         BitmapCropTask.OnEndCropHandler onEndCrop = new BitmapCropTask.OnEndCropHandler() {
@@ -355,7 +366,7 @@
         };
         BitmapCropTask cropTask = new BitmapCropTask(getContext(), res, resId,
                 crop, rotation, outSize.x, outSize.y, true, false, onEndCrop);
-        cropTask.execute();
+        NycWallpaperUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
     }
 
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@@ -457,7 +468,7 @@
         if (onBitmapCroppedHandler != null) {
             cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
         }
-        cropTask.execute();
+        NycWallpaperUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
     }
 
     protected void updateWallpaperDimensions(int width, int height) {
@@ -486,8 +497,32 @@
         TileSource result;
     }
 
-    interface CropViewScaleAndOffsetProvider {
-        float getScale(Point wallpaperSize, RectF crop);
-        float getParallaxOffset();
+    public static class CropViewScaleAndOffsetProvider {
+        public float getScale(Point wallpaperSize, RectF crop) {
+            return 1f;
+        }
+
+        public float getParallaxOffset() {
+            return 0.5f;
+        }
+
+        public void updateCropView(WallpaperCropActivity a, TileSource src) {
+            Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
+                    a.getResources(), a.getWindowManager());
+            RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
+                    wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
+
+            float scale = getScale(wallpaperSize, crop);
+            PointF center = a.mCropView.getCenter();
+
+            // Offsets wallpaper preview according to the state it will be displayed in upon
+            // returning home. Offset ranges from 0 to 1, where 0 is the leftmost parallax and
+            // 1 is the rightmost.
+            // Make sure the offset is in the correct range.
+            float offset = Math.max(0, Math.min(getParallaxOffset(), 1));
+            float screenWidth = a.mCropView.getWidth() / scale;
+            center.x = screenWidth / 2 + offset * (crop.width() - screenWidth) + crop.left;
+            a.mCropView.setScaleAndCenter(scale, center.x, center.y);
+        }
     }
 }
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 5d41238..40f0544 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -31,10 +31,13 @@
 import android.database.DataSetObserver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.PorterDuff;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -44,6 +47,7 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.provider.MediaStore;
+import android.support.annotation.NonNull;
 import android.util.Log;
 import android.util.Pair;
 import android.view.ActionMode;
@@ -77,13 +81,16 @@
 import com.android.photos.BitmapRegionTileSource;
 import com.android.photos.BitmapRegionTileSource.BitmapSource;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 
 public class WallpaperPickerActivity extends WallpaperCropActivity {
-    static final String TAG = "Launcher.WallpaperPickerActivity";
+    static final String TAG = "WallpaperPickerActivity";
 
     public static final int IMAGE_PICK = 5;
     public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
@@ -171,12 +178,45 @@
         public void onSave(final WallpaperPickerActivity a) {
             boolean finishActivityWhenDone = true;
             BitmapCropTask.OnBitmapCroppedHandler h = new BitmapCropTask.OnBitmapCroppedHandler() {
-                public void onBitmapCropped(byte[] imageBytes) {
+                @Override
+                public void onBitmapCropped(byte[] imageBytes, Rect hint) {
+                    Bitmap thumb = null;
                     Point thumbSize = getDefaultThumbnailSize(a.getResources());
-                    // rotation is set to 0 since imageBytes has already been correctly rotated
-                    Bitmap thumb = createThumbnail(
-                            thumbSize, null, null, imageBytes, null, 0, 0, true);
-                    a.getSavedImages().writeImage(thumb, imageBytes);
+                    if (imageBytes != null) {
+                        // rotation is set to 0 since imageBytes has already been correctly rotated
+                        thumb = createThumbnail(
+                                thumbSize, null, null, imageBytes, null, 0, 0, true);
+                        a.getSavedImages().writeImage(thumb, imageBytes);
+                    } else {
+                        try {
+                            // Generate thumb
+                            Point size = getDefaultThumbnailSize(a.getResources());
+                            Rect finalCropped = new Rect();
+                            Utils.getMaxCropRect(hint.width(), hint.height(), size.x, size.y, false)
+                                    .roundOut(finalCropped);
+                            finalCropped.offset(hint.left, hint.top);
+
+                            InputStream in = a.getContentResolver().openInputStream(mUri);
+                            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(in, true);
+
+                            BitmapFactory.Options options = new BitmapFactory.Options();
+                            options.inSampleSize = finalCropped.width() / size.x;
+                            thumb = decoder.decodeRegion(finalCropped, options);
+                            decoder.recycle();
+                            Utils.closeSilently(in);
+                            if (thumb != null) {
+                                thumb = Bitmap.createScaledBitmap(thumb, size.x, size.y, true);
+                            }
+                        } catch (IOException e) { }
+                        PointF center = a.mCropView.getCenter();
+
+                        Float[] extras = new Float[] {
+                                a.mCropView.getScale(),
+                                center.x,
+                                center.y
+                        };
+                        a.getSavedImages().writeImage(thumb, mUri, extras);
+                    }
                 }
             };
             boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -193,7 +233,7 @@
     }
 
     public static class FileWallpaperInfo extends WallpaperTileInfo {
-        private File mFile;
+        protected File mFile;
 
         public FileWallpaperInfo(File target, Drawable thumb) {
             mFile = target;
@@ -204,7 +244,8 @@
             a.setWallpaperButtonEnabled(false);
             final BitmapRegionTileSource.UriBitmapSource bitmapSource =
                     new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
-            a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
+            a.setCropViewTileSource(bitmapSource, false, true, getCropViewScaleAndOffsetProvider(),
+                    new Runnable() {
 
                 @Override
                 public void run() {
@@ -214,6 +255,11 @@
                 }
             });
         }
+
+        protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
+            return null;
+        }
+
         @Override
         public void onSave(WallpaperPickerActivity a) {
             boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
@@ -300,32 +346,81 @@
             LoadRequest req = new LoadRequest();
             req.moveToLeft = false;
             req.touchEnabled = false;
-            req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider() {
-
-                @Override
-                public float getScale(Point wallpaperSize, RectF crop) {
-                    return 1f;
-                }
-
-                @Override
-                public float getParallaxOffset() {
-                    return 0.5f;
-                }
-            };
+            req.scaleAndOffsetProvider = new CropViewScaleAndOffsetProvider();
             req.result = new DrawableTileSource(a.getContext(),
                     defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
             a.onLoadRequestComplete(req, true);
         }
         @Override
-        public void onSave(WallpaperPickerActivity a) {
-            try {
-                WallpaperManager.getInstance(a.getContext()).clear();
-                a.setResult(Activity.RESULT_OK);
-            } catch (IOException e) {
-                Log.w("Setting wallpaper to default threw exception", e);
+        public void onSave(final WallpaperPickerActivity a) {
+            if (!Utilities.isNycOrAbove()) {
+                try {
+                    WallpaperManager.getInstance(a.getContext()).clear();
+                    a.setResult(Activity.RESULT_OK);
+                } catch (IOException e) {
+                    Log.e(TAG, "Setting wallpaper to default threw exception", e);
+                } catch (SecurityException e) {
+                    Log.w(TAG, "Setting wallpaper to default threw exception", e);
+                    // In this case, clearing worked; the exception was thrown afterwards.
+                    a.setResult(Activity.RESULT_OK);
+                }
+                a.finish();
+            } else {
+                BitmapCropTask.OnEndCropHandler onEndCropHandler
+                        = new BitmapCropTask.OnEndCropHandler() {
+                    @Override
+                    public void run(boolean cropSucceeded) {
+                        if (cropSucceeded) {
+                            a.setResult(Activity.RESULT_OK);
+                        }
+                        a.finish();
+                    }
+                };
+                BitmapCropTask setWallpaperTask = getDefaultWallpaperCropTask(a, onEndCropHandler);
+
+                NycWallpaperUtils.executeCropTaskAfterPrompt(a, setWallpaperTask,
+                        a.getOnDialogCancelListener());
             }
-            a.finish();
         }
+
+        @NonNull
+        private BitmapCropTask getDefaultWallpaperCropTask(final WallpaperPickerActivity a,
+                final BitmapCropTask.OnEndCropHandler onEndCropHandler) {
+            return new BitmapCropTask(a, null, null, -1, -1, -1,
+                    true, false, onEndCropHandler) {
+                @Override
+                protected Boolean doInBackground(Integer... params) {
+                    int whichWallpaper = params[0];
+                    boolean succeeded = true;
+                    try {
+                        if (whichWallpaper == NycWallpaperUtils.FLAG_SET_LOCK) {
+                            Bitmap defaultWallpaper = ((BitmapDrawable) WallpaperManager
+                                    .getInstance(a.getApplicationContext()).getBuiltInDrawable())
+                                    .getBitmap();
+                            ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
+                            if (defaultWallpaper.compress(Bitmap.CompressFormat.PNG, 100,
+                                    tmpOut)) {
+                                byte[] outByteArray = tmpOut.toByteArray();
+                                NycWallpaperUtils.setStream(a.getApplicationContext(),
+                                        new ByteArrayInputStream(outByteArray), null, true,
+                                        NycWallpaperUtils.FLAG_SET_LOCK);
+                            }
+                        } else {
+                            NycWallpaperUtils.clear(a, whichWallpaper);
+                        }
+                    } catch (IOException e) {
+                        Log.e(TAG, "Setting wallpaper to default threw exception", e);
+                        succeeded = false;
+                    } catch (SecurityException e) {
+                        Log.w(TAG, "Setting wallpaper to default threw exception", e);
+                        // In this case, clearing worked; the exception was thrown afterwards.
+                        succeeded = true;
+                    }
+                    return succeeded;
+                }
+            };
+        }
+
         @Override
         public boolean isSelectable() {
             return true;
@@ -442,10 +537,10 @@
                     }
                     return;
                 }
-                setWallpaperButtonEnabled(true);
                 WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
                 if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
                     selectTile(v);
+                    setWallpaperButtonEnabled(true);
                 }
                 info.onClick(WallpaperPickerActivity.this);
             }
@@ -561,7 +656,7 @@
                 new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
-                        // Ensure that a tile is slelected and loaded.
+                        // Ensure that a tile is selected and loaded.
                         if (mSelectedTile != null && mCropView.getTileSource() != null) {
                             // Prevent user from selecting any new tile.
                             mWallpaperStrip.setVisibility(View.GONE);
@@ -570,9 +665,9 @@
                             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();
+                            // This case shouldn't be possible, since "Set wallpaper" is disabled
+                            // until user clicks on a title.
+                            Log.w(TAG, "\"Set wallpaper\" was clicked when no tile was selected");
                         }
                     }
                 });
@@ -849,7 +944,7 @@
                 (int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
         cropTask.setCropBounds(cropRect);
 
-        if (cropTask.cropBitmap()) {
+        if (cropTask.cropBitmap(NycWallpaperUtils.FLAG_SET_SYSTEM)) {
             return cropTask.getCroppedBitmap();
         } else {
             return null;
@@ -1195,11 +1290,6 @@
 
     @Override
     public boolean enableRotation() {
-        // Check if rotation is enabled for this device.
-        if (Utilities.isRotationAllowedForDevice(getContext()))
-            return true;
-
-        // Check if the user has specifically enabled rotation via preferences.
-        return Utilities.isAllowRotationPrefEnabled(getApplicationContext(), true);
+        return true;
     }
 }
diff --git a/build.gradle b/build.gradle
index 44f5b7c..b9a990f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,7 +3,7 @@
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:+'
+        classpath 'com.android.tools.build:gradle:1.5.0'
         classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.0'
     }
 }
@@ -51,13 +51,13 @@
 }
 
 dependencies {
-    compile 'com.android.support:support-v4:23.0.1'
-    compile 'com.android.support:recyclerview-v7:23.0.1'
+    compile 'com.android.support:support-v4:23.1.1'
+    compile 'com.android.support:recyclerview-v7:23.1.1'
     compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-2'
 
     testCompile 'junit:junit:4.12'
-    androidTestCompile 'com.android.support.test:runner:+'
-    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:+'
+    androidTestCompile 'com.android.support.test:runner:0.5'
+    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
 }
 
 protobuf {
diff --git a/proguard.flags b/proguard.flags
index 7725800..a167663 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -70,3 +70,10 @@
   public float getBackgroundAlpha();
   public void setBackgroundAlpha(float);
 }
+
+# Proguard will strip new callbacks in LauncherApps.Callback from
+# WrappedCallback if compiled against an older SDK. Don't let this happen.
+-keep class com.android.launcher3.compat.** {
+  *;
+}
+
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 1a951f1..b1f85b4 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -72,10 +72,4 @@
             android:visibility="invisible" />
     </com.android.launcher3.DragLayer>
 
-    <ViewStub
-        android:id="@+id/launcher_overlay_stub"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:inflatedId="@+id/launcher_overlay"
-        android:layout="@layout/launcher_overlay" />
 </com.android.launcher3.LauncherRootView>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 8bf9d64..962b5ce 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -82,10 +82,4 @@
             android:visibility="invisible" />
     </com.android.launcher3.DragLayer>
 
-    <ViewStub
-        android:id="@+id/launcher_overlay_stub"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:inflatedId="@+id/launcher_overlay"
-        android:layout="@layout/launcher_overlay" />
 </com.android.launcher3.LauncherRootView>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 2fc62c5..50daaa9 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -80,11 +80,4 @@
             android:visibility="invisible" />
     </com.android.launcher3.DragLayer>
 
-    <ViewStub
-        android:id="@+id/launcher_overlay_stub"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:inflatedId="@+id/launcher_overlay"
-        android:layout="@layout/launcher_overlay" />
-
 </com.android.launcher3.LauncherRootView>
diff --git a/res/layout/launcher_overlay_example.xml b/res/layout/launcher_overlay_example.xml
deleted file mode 100644
index 7d92d4f..0000000
--- a/res/layout/launcher_overlay_example.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:layout_ignoreInsets="true">
-
-    <FrameLayout
-        android:id="@+id/search_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="#ff00ff00"
-        android:visibility="invisible" />
-
-    <FrameLayout
-        android:id="@+id/search_box"
-        android:layout_width="match_parent"
-        android:layout_height="48dp"
-        android:layout_marginLeft="8dp"
-        android:layout_marginRight="8dp"
-        android:layout_marginTop="36dp"
-        android:background="#ffff0000" />
-</FrameLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 6ea6f4a..f9e1cff 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Laat draai toe"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Verwyder"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index ad9c7f9..8bf17f7 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"በእርስዎ አስተዳዳሪ የተሰናከለ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"ማሽከርከርን ይፍቀዱ"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"የማይታወቅ"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"አስወግድ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 9d2c42b..ba4def2 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"عطَّل المشرف هذه الميزة"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"السماح بالتدوير"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"غير معروفة"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"إزالة"</string>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 76cfaa3..476f2ab 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -37,8 +37,8 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritlər-də yer yoxdur"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"Tətbiqlər"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Əsas səhifə"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"Silin"</string>
-    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Sistemdən silin"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Kənarlaşdır"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Sistemdən sil"</string>
     <string name="info_target_label" msgid="8053346143994679532">"Tətbiq məlumatı"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"qısayolları quraşdır"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir."</string>
@@ -71,6 +71,7 @@
     <string name="widget_button_text" msgid="2880537293434387943">"Vidcet"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Divar kağızları"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Ayarlar"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Admininiz tərəfindən deaktiv edilib"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Fırlatmağa icazə verin"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Naməlum"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Yığışdır"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..d2168c2
--- /dev/null
+++ b/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,107 @@
+<?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="app_name" msgid="649227358658669779">"Launcher3"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
+    <string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Preuzeta aplikacija je onemogućena u Bezbednom režimu"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Vidžeti su onemogućeni u Bezbednom režimu"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite i zadržite da biste izabrali vidžet."</string>
+    <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dvaput dodirnite i zadržite da biste izabrali vidžet ili koristite prilagođene radnje."</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Pretražite aplikacije..."</string>
+    <string name="all_apps_loading_message" msgid="7557140873644765180">"Aplikacije se učitavaju..."</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nije pronađena nijedna aplikacija za „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
+    <string name="all_apps_search_market_message" msgid="5470761048755751471">"Idi na aplikaciju <xliff:g id="QUERY">%1$s</xliff:g>"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Nema više prostora na ovom početnom ekranu."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora na traci Omiljeno"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacije"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Početna"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Ukloni"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Deinstaliraj"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Informacije o aplikaciji"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliranje prečica"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Dozvoljava aplikaciji da dodaje prečice bez intervencije korisnika."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"čitanje podešavanja i prečica na početnom ekranu"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Dozvoljava aplikaciji da čita podešavanja i prečice na početnom ekranu."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"upisivanje podešavanja i prečica na početnom ekranu"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Dozvoljava aplikaciji da menja podešavanja i prečice na početnom ekranu."</string>
+    <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nema dozvolu za upućivanje telefonskih poziva"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Problem pri učitavanju vidžeta"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Podešavanje"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može da se deinstalira."</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Neimenovani direktorijum"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"%1$d. stranica od %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d. početni ekran od %2$d"</string>
+    <string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog ekrana"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Dobro došli"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopirajte ikone aplikacija"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Uvesti ikone i direktorijume sa starih početnih ekrana?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJTE IKONE"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"POČNITE ISPOČETKA"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadine, vidžeti i podešavanja"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Dodirnite i zadržite pozadinu da biste prilagodili"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"VAŽI"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Direktorijum je otvoren, <xliff:g id="WIDTH">%1$d</xliff:g> puta <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Dodirnite da biste zatvorili direktorijum"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Dodirnite da biste sačuvali promenu imena"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Direktorijum je zatvoren"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Direktorijum je preimenovan u <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Direktorijum: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Vidžeti"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Podešavanja"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator je onemogućio"</string>
+    <string name="allow_rotation_title" msgid="2118706734511831751">"Dozvoli rotaciju"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
+    <string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"Pretraži"</string>
+    <string name="abandoned_promises_title" msgid="7096178467971716750">"Ova aplikacija nije instalirana"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija za ovu ikonu nije instalirana. Možete da je uklonite ili da potražite aplikaciju i instalirate je ručno."</string>
+    <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+    <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka na instaliranje"</string>
+    <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodaj na početni ekran"</string>
+    <string name="action_move_here" msgid="2170188780612570250">"Premesti stavku ovde"</string>
+    <string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodata na početni ekran"</string>
+    <string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
+    <string name="action_move" msgid="4339390619886385032">"Premesti stavku"</string>
+    <string name="move_to_empty_cell" msgid="2833711483015685619">"Premesti u red <xliff:g id="NUMBER_0">%1$s</xliff:g> i kolonu <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+    <string name="move_to_position" msgid="6750008980455459790">"Premesti na <xliff:g id="NUMBER">%1$s</xliff:g>. poziciju"</string>
+    <string name="move_to_hotseat_position" msgid="6295412897075147808">"Premesti na <xliff:g id="NUMBER">%1$s</xliff:g>. poziciju u omiljenim"</string>
+    <string name="item_moved" msgid="4606538322571412879">"Stavka je premeštena"</string>
+    <string name="add_to_folder" msgid="9040534766770853243">"Dodaj u direktorijum: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="add_to_folder_with_app" msgid="4534929978967147231">"Dodaj u direktorijum u kome je <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="added_to_folder" msgid="4793259502305558003">"Stavka je dodata u direktorijum"</string>
+    <string name="create_folder_with" msgid="4050141361160214248">"Napravite direktorijum sa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_created" msgid="6409794597405184510">"Direktorijum je napravljen"</string>
+    <string name="action_move_to_workspace" msgid="1603837886334246317">"Premesti na početni ekran"</string>
+    <string name="action_move_screen_left" msgid="8854216831569401665">"Pomeri ekran ulevo"</string>
+    <string name="action_move_screen_right" msgid="329334910274311123">"Pomeri ekran udesno"</string>
+    <string name="screen_moved" msgid="266230079505650577">"Ekran je pomeren"</string>
+    <string name="action_resize" msgid="1802976324781771067">"Promeni veličinu"</string>
+    <string name="action_increase_width" msgid="8773715375078513326">"Povećaj širinu"</string>
+    <string name="action_increase_height" msgid="459390020612501122">"Povećaj visinu"</string>
+    <string name="action_decrease_width" msgid="1374549771083094654">"Smanji širinu"</string>
+    <string name="action_decrease_height" msgid="282377193880900022">"Smanji visinu"</string>
+    <string name="widget_resized" msgid="9130327887929620">"Veličina vidžeta je promenjena na širinu <xliff:g id="NUMBER_0">%1$s</xliff:g> i visinu <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+</resources>
diff --git a/res/values-be-rBY/strings.xml b/res/values-be-rBY/strings.xml
new file mode 100644
index 0000000..47fbf8c
--- /dev/null
+++ b/res/values-be-rBY/strings.xml
@@ -0,0 +1,107 @@
+<?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="app_name" msgid="649227358658669779">"Launcher3"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="work_folder_name" msgid="3753320833950115786">"Працоўная"</string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Праграма не ўсталявана."</string>
+    <string name="activity_not_available" msgid="7456344436509528827">"Праграма недаступная"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Спампаваная праграма адключана ў Бяспечным рэжыме"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Віджэты адключаны ў Бяспечным рэжыме"</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Дакраніцеся і ўтрымлiвайце віджэт, каб выбр. яго."</string>
+    <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Дакраніцеся двойчы і ўтрымлівайце, каб выбраць віджэт або выкарыстоўваць карыстальніцкія дзеянні."</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Пошук у Праграмах..."</string>
+    <string name="all_apps_loading_message" msgid="7557140873644765180">"Ідзе загрузка праграм…"</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"Праграм, якія адпавядаюць запыту \"<xliff:g id="QUERY">%1$s</xliff:g>\", не знойдзена"</string>
+    <string name="all_apps_search_market_message" msgid="5470761048755751471">"Перайсці да <xliff:g id="QUERY">%1$s</xliff:g>"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"На гэтым Галоўным экране больш няма месца."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"У латку \"Абранае\" больш няма месца"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Праграмы"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Галоўная"</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="permlab_install_shortcut" msgid="5632423390354674437">"усталёўваць ярлыкі"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Дазваляе праграмам дадаваць ярлыкі без умяшання карыстальніка."</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="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> не мае дазволу на здзяйсненне тэлефонных званкоў"</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="folder_hint_text" msgid="6617836969016293992">"Папка без назвы"</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="workspace_new_page" msgid="257366611030256142">"Новая старонка галоўнага экрана"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Вітаем"</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_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_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="msg_disabled_by_admin" msgid="6898038085516271325">"Адключаная адміністратарам"</string>
+    <string name="allow_rotation_title" msgid="2118706734511831751">"Дазволіць паварот"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Невядома"</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>
+    <string name="app_downloading_title" msgid="8336702962104482644">"Ідзе спампоўка <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завершана"</string>
+    <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чакае ўсталёўкі"</string>
+    <string name="action_add_to_workspace" msgid="8902165848117513641">"Дадаць на Галоўны экран"</string>
+    <string name="action_move_here" msgid="2170188780612570250">"Перамясціць элемент сюды"</string>
+    <string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент дададзены на галоўны экран"</string>
+    <string name="item_removed" msgid="851119963877842327">"Элемент выдалены"</string>
+    <string name="action_move" msgid="4339390619886385032">"Перамясціць элемент"</string>
+    <string name="move_to_empty_cell" msgid="2833711483015685619">"Перамясціць у радок <xliff:g id="NUMBER_0">%1$s</xliff:g> слупок <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+    <string name="move_to_position" msgid="6750008980455459790">"Перамясціць у пазіцыю <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="move_to_hotseat_position" msgid="6295412897075147808">"Перамясціць у абранае, у пазіцыю <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="item_moved" msgid="4606538322571412879">"Элемент перамешчаны"</string>
+    <string name="add_to_folder" msgid="9040534766770853243">"Дадаць у папку: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="add_to_folder_with_app" msgid="4534929978967147231">"Дадаць у папку з <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="added_to_folder" msgid="4793259502305558003">"Элемент дададзены ў папку"</string>
+    <string name="create_folder_with" msgid="4050141361160214248">"Стварыць папку з: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_created" msgid="6409794597405184510">"Папка створана"</string>
+    <string name="action_move_to_workspace" msgid="1603837886334246317">"Перамясціць на Галоўны экран"</string>
+    <string name="action_move_screen_left" msgid="8854216831569401665">"Перамясціць экран налева"</string>
+    <string name="action_move_screen_right" msgid="329334910274311123">"Перамясціць экран направа"</string>
+    <string name="screen_moved" msgid="266230079505650577">"Экран перамешчаны"</string>
+    <string name="action_resize" msgid="1802976324781771067">"Змяніць памер"</string>
+    <string name="action_increase_width" msgid="8773715375078513326">"Павялічыць шырыню"</string>
+    <string name="action_increase_height" msgid="459390020612501122">"Павялічыць вышыню"</string>
+    <string name="action_decrease_width" msgid="1374549771083094654">"Паменшыць шырыню"</string>
+    <string name="action_decrease_height" msgid="282377193880900022">"Паменшыць вышыню"</string>
+    <string name="widget_resized" msgid="9130327887929620">"Памеры віджэта зменены на: шырыня <xliff:g id="NUMBER_0">%1$s</xliff:g>, вышыня <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 9c96cd8..5de4747 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Разрешаване на завъртането"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Няма информация"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Премахване"</string>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index d142c82..8a7f517 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -60,7 +60,7 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"আইকনগুলি কপি করুন"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"নতুন করে শুরু করুন"</string>
     <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ওয়ালপেপার, উইজেট এবং সেটিংস"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"নিজের পছন্দমত সাজানোর জন্য পটভূমি স্পর্শ করে ধরে থাকুন"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"কাস্টমাইজ করার জন্য পটভূমি স্পর্শ করে ধরে থাকুন"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"বুঝেছি"</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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"ঘূর্ণনের অনুমতি দিন"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
diff --git a/res/values-bs-rBA/strings.xml b/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..f25548a
--- /dev/null
+++ b/res/values-bs-rBA/strings.xml
@@ -0,0 +1,107 @@
+<?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="app_name" msgid="649227358658669779">"Launcher3"</string>
+    <string name="folder_name" msgid="7371454440695724752"></string>
+    <string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
+    <string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
+    <string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"Preuzeta aplikacija je onemogućena u sigurnom načinu rada"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Vidžeti su onemogućeni u sigurnom načinu rada."</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite &amp; i držite da biste uzeli dodatak."</string>
+    <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dvaput dodirnite &amp; i držite da biste uzeli vidžet ili koristite prilagođene radnje."</string>
+    <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Pretraži aplikacije"</string>
+    <string name="all_apps_loading_message" msgid="7557140873644765180">"Aplikacije se učitavaju…"</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nije pronađena nijedna aplikacija koja odgovara upitu \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
+    <string name="all_apps_search_market_message" msgid="5470761048755751471">"Idite na uslugu <xliff:g id="QUERY">%1$s</xliff:g>"</string>
+    <string name="out_of_space" msgid="4691004494942118364">"Na ovom početnom ekranu nema više prostora."</string>
+    <string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora u ladici Favoriti"</string>
+    <string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacije"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Tipka za početak"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Ukloni"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Ukloni"</string>
+    <string name="info_target_label" msgid="8053346143994679532">"Informacije o aplikaciji"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliraj prečice"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"Dopušta aplikaciji dodavanje prečica bez posredovanja korisnika."</string>
+    <string name="permlab_read_settings" msgid="1941457408239617576">"čitaj postavke na početnom ekranu i prečice"</string>
+    <string name="permdesc_read_settings" msgid="5833423719057558387">"Dopušta aplikaciji čitanje postavki i prečica na početnom ekranu."</string>
+    <string name="permlab_write_settings" msgid="3574213698004620587">"zapisuj postavke na početnom ekranu i prečice"</string>
+    <string name="permdesc_write_settings" msgid="5440712911516509985">"Dopušta aplikaciji promjenu postavki i prečica na početnom ekranu."</string>
+    <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nema dozvolu da uspostavlja telefonske pozive"</string>
+    <string name="gadget_error_text" msgid="6081085226050792095">"Problem pri učitavanju dodatka"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"Postavljanje"</string>
+    <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može se deinstalirati."</string>
+    <string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana fascikla"</string>
+    <string name="default_scroll_format" msgid="7475544710230993317">"Strana %1$d od %2$d"</string>
+    <string name="workspace_scroll_format" msgid="8458889198184077399">"Početni ekran %1$d od %2$d"</string>
+    <string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog ekrana"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Dobrodošli"</string>
+    <string name="migration_cling_title" msgid="9181776667882933767">"Kopirajte ikone aplikacije"</string>
+    <string name="migration_cling_description" msgid="2752413805582227644">"Uvoz ikone i foldera sa starih početnih ekrana?"</string>
+    <string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJ IKONE"</string>
+    <string name="migration_cling_use_default" msgid="2626475813981258626">"POČNITE ISPOČETKA"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadine, vidžeti, &amp; amp; podešavanja"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Dodirnite &amp; i držite pozadinu za prilagođavanje"</string>
+    <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"JASNO MI JE"</string>
+    <string name="folder_opened" msgid="94695026776264709">"Fascikla je otvorena, (š) <xliff:g id="WIDTH">%1$d</xliff:g> (v) <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1884479294466410023">"Dodirnite da biste zatvorili fasciklu"</string>
+    <string name="folder_tap_to_rename" msgid="9191075570492871147">"Dodirnite da biste sačuvali promjenu imena"</string>
+    <string name="folder_closed" msgid="4100806530910930934">"Fascikla je zatvorena"</string>
+    <string name="folder_renamed" msgid="1794088362165669656">"Ime fascikle je promijenjeno u <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="6629239338071103179">"Fascikla: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"Dodaci"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"Postavke"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio vaš administrator"</string>
+    <string name="allow_rotation_title" msgid="2118706734511831751">"Dopusti rotaciju"</string>
+    <string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</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">"Ova aplikacija nije instalirana"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija za ovu ikonu nije instalirana. Možete je ukloniti ili potražiti aplikaciju i ručno je instalirati."</string>
+    <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+    <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka da se instalira"</string>
+    <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodaj na početni ekran"</string>
+    <string name="action_move_here" msgid="2170188780612570250">"Premjesti stavku ovdje"</string>
+    <string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodana na Početni ekran."</string>
+    <string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
+    <string name="action_move" msgid="4339390619886385032">"Premjesti stavku"</string>
+    <string name="move_to_empty_cell" msgid="2833711483015685619">"Pomjeri stavku u red <xliff:g id="NUMBER_0">%1$s</xliff:g> kolonu <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+    <string name="move_to_position" msgid="6750008980455459790">"Pomjeri stavku na poziciju <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <string name="move_to_hotseat_position" msgid="6295412897075147808">"Pomjeri stavku na poziciju <xliff:g id="NUMBER">%1$s</xliff:g> među favoritima"</string>
+    <string name="item_moved" msgid="4606538322571412879">"Stavka je premještena"</string>
+    <string name="add_to_folder" msgid="9040534766770853243">"Dodaj u folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="add_to_folder_with_app" msgid="4534929978967147231">"Dodaj u folder sa aplikacijom <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="added_to_folder" msgid="4793259502305558003">"Stavka je dodana u folder"</string>
+    <string name="create_folder_with" msgid="4050141361160214248">"Kreirajte folder sa stavkom: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_created" msgid="6409794597405184510">"Folder je kreiran"</string>
+    <string name="action_move_to_workspace" msgid="1603837886334246317">"Pomjeri na početni ekran"</string>
+    <string name="action_move_screen_left" msgid="8854216831569401665">"Pomjeri ekran ulijevo"</string>
+    <string name="action_move_screen_right" msgid="329334910274311123">"Pomjeri ekran udesno"</string>
+    <string name="screen_moved" msgid="266230079505650577">"Ekran je pomjeren"</string>
+    <string name="action_resize" msgid="1802976324781771067">"Promijeni veličinu"</string>
+    <string name="action_increase_width" msgid="8773715375078513326">"Povećaj širinu"</string>
+    <string name="action_increase_height" msgid="459390020612501122">"Povećaj visinu"</string>
+    <string name="action_decrease_width" msgid="1374549771083094654">"Smanji širinu"</string>
+    <string name="action_decrease_height" msgid="282377193880900022">"Smanji visinu"</string>
+    <string name="widget_resized" msgid="9130327887929620">"Veličina vidžeta je promijenjena na širinu <xliff:g id="NUMBER_0">%1$s</xliff:g> visinu <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index f673945..9f66f3f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permet la rotació"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 373ae83..baffa1b 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázáno administrátorem"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Povolit otáčení"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 3654b72..13d0873 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Deaktiveret af din administrator"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Tillad rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Ukendt"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index a375ecd..9b66be3 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Von deinem Administrator deaktiviert"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Drehung zulassen"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Unbekannt"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Entfernen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index bdc62c8..5b47e1b 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Να επιτρέπεται η περιστροφή"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Άγνωστο"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Κατάργηση"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index b86987c..dff24f8 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -59,7 +59,7 @@
     <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_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets &amp; settings"</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_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index b86987c..dff24f8 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -59,7 +59,7 @@
     <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_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets &amp; settings"</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_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index b86987c..dff24f8 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -59,7 +59,7 @@
     <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_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets &amp; settings"</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_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index cc58b46..104cae6 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"El administrador inhabilitó esta función"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir la rotación"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index ab469dd..5256dda 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está completa"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"Aplicaciones"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"Quitar"</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 de la aplicación"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar accesos directos"</string>
@@ -71,12 +71,13 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitada por el administrador"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotación"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
-    <string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</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 quitar el icono o buscar la aplicación e instalarla manualmente."</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>
     <string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="action_add_to_workspace" msgid="8902165848117513641">"Añadir a la pantalla de inicio"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 053791d..b9540a5 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Luba pööramine"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Teadmata"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Eemalda"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 4b44c21..8201dd8 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -26,7 +26,7 @@
     <string name="activity_not_available" msgid="7456344436509528827">"Ez dago erabilgarri aplikazioa"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Deskargatutako aplikazioa modu seguruan desgaitu da"</string>
     <string name="safemode_widget_error" msgid="4863470563535682004">"Widgetak desgaitu egin dira modu seguruan"</string>
-    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Eduki sakatuta widgeta aukeratzeko."</string>
+    <string name="long_press_widget_to_add" msgid="7699152356777458215">"Eduki ukituta widgeta aukeratzeko."</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Sakatu birritan eta eduki sakatuta widgeta aukeratzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Bilatu aplikazioetan…"</string>
@@ -60,7 +60,7 @@
     <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_longpress_title" msgid="9173998993909018310">"Horma-paperak, widgetak eta ezarpenak"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pertsonalizatzeko, eduki sakatuta atzeko planoa"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pertsonalizatzeko, eduki ukituta atzeko planoa"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Baimendu biratzeko aukera"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Ezezaguna"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Kendu"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 125e79e..73413dc 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"فضای بیشتری در سینی موارد دلخواه وجود ندارد"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"برنامه‌ها"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"صفحه اصلی"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"برداشتن"</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="permlab_install_shortcut" msgid="5632423390354674437">"نصب میان‌برها"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"توسط سرپرست سیستم غیرفعال شده است"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"چرخش مجاز است"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"حذف"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 03df292..52a47c7 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -60,7 +60,7 @@
     <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_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_description" msgid="4119994475505235248">"Muokkaa taustaa koskettamalla ja painamalla pitkään"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SELVÄ"</string>
     <string name="folder_opened" msgid="94695026776264709">"Kansio avattu, koko <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">"Sulje kansio koskettamalla"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Järjestelmänvalvoja on poistanut toiminnon käytöstä."</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Salli kierto"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Tuntematon"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Poista"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 5a338ae..3718486 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -60,7 +60,7 @@
     <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_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 le personnaliser"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Maintenez un doigt sur le fond d\'écran pour le personnaliser"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"J\'ai compris"</string>
     <string name="folder_opened" msgid="94695026776264709">"Dossier ouvert, <xliff:g id="WIDTH">%1$d</xliff:g> par <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"Toucher pour fermer le dossier"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Cette fonction est désactivée par votre administrateur"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permettre la rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f189c63..b9f90bc 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Autoriser la rotation"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index a35b03e..91e1ac3 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -29,7 +29,7 @@
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premido un widget para seleccionalo."</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Toca dúas veces e mantén premido para seleccionar un widget ou utiliza accións personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
-    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Buscar aplicacións..."</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Aplicacións de busca..."</string>
     <string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicacións..."</string>
     <string name="all_apps_no_search_results" msgid="6332185285860416787">"Non se atoparon aplicacións que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
     <string name="all_apps_search_market_message" msgid="5470761048755751471">"Ir a <xliff:g id="QUERY">%1$s</xliff:g>"</string>
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"Non hai máis espazo na bandexa de favoritos"</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_target_label" msgid="1822697352535677073">"Quitar"</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="permlab_install_shortcut" msgid="5632423390354674437">"instalar atallos"</string>
@@ -59,8 +59,8 @@
     <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_longpress_title" msgid="9173998993909018310">"Fondos de pantalla, widgets e configuración"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén premido o fondo para personalizalo"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos pantalla, widgets e configuración"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén tocado o segundo plano para personalizar"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"DE ACORDO"</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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir xiro"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index c42348f..3ce8676 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -30,12 +30,12 @@
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"વિજેટ ચૂંટવા અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટેપ કરો અને પકડી રાખો."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"ઍપ્લિકેશનોમાં શોધો…"</string>
-    <string name="all_apps_loading_message" msgid="7557140873644765180">"ઍપ્લિકેશનો લોડ કરી રહ્યું છે…"</string>
-    <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી"</string>
+    <string name="all_apps_loading_message" msgid="7557140873644765180">"એપ્લિકેશનો લોડ કરી રહ્યું છે…"</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" થી મેળ ખાતી કોઈ એપ્લિકેશનો મળી નથી"</string>
     <string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g> પર જાઓ"</string>
     <string name="out_of_space" msgid="4691004494942118364">"આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી."</string>
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"મનપસંદ ટ્રે પર વધુ જગ્યા નથી"</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_target_label" msgid="1822697352535677073">"દૂર કરો"</string>
     <string name="delete_target_uninstall_label" msgid="5100785476250872595">"અનઇન્સ્ટોલ કરો"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"પરિભ્રમણને મંજૂરી આપો"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"અજાણ્યો"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"દૂર કરો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index d2de54c..5d10d3a 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"आपके व्यवस्थापक द्वारा अक्षम"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"रोटेशन की अनुमति दें"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 427e5c8..cdae4ed 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -71,6 +71,7 @@
     <string name="widget_button_text" msgid="2880537293434387943">"Widgeti"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Postavke"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio administrator"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Dopusti rotaciju"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index a1d7e6d..400a426 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -37,8 +37,8 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"Nincs több hely a Kedvencek tálcán"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"Alkalmazások"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Főoldal"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"Törlés"</string>
-    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Eltávolítás"</string>
+    <string name="delete_target_label" msgid="1822697352535677073">"Eltávolítás"</string>
+    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"Törlés"</string>
     <string name="info_target_label" msgid="8053346143994679532">"Alkalmazásinformáció"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"parancsikonok telepítése"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat."</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Elforgatás engedélyezése"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Ismeretlen"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Eltávolítás"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 74d98d6..79bc330 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Անջատվել է ձեր ադմինիստրատորի կողմից"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Թույլ տալ պարբերական կրկնությունը"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 1dda24b..a48c56f 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Dinonaktifkan oleh admin"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Izinkan putaran"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Tidak dikenal"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Buang"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index fd6977c..5e2a07a 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Leyfa snúning"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Óþekkt"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjarlægja"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 46040f5..0e89887 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Consenti rotazione"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index bb1ee5a..8d0dc2d 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"אין עוד מקום במגש המועדפים"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"אפליקציות"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"דף הבית"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"מחק"</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="permlab_install_shortcut" msgid="5632423390354674437">"התקן קיצורי דרך"</string>
@@ -60,7 +60,7 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"העתק סמלים"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"התחל דף חדש"</string>
     <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"טפטים, ווידג\'טים והגדרות"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"גע והחזק ברקע כדי לבצע התאמה אישית"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"גע והחזק ברקע לביצוע התאמה אישית"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"הבנתי"</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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"אפשרות סיבוב"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"הסר"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index e3c3194..69ae46e 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"回転を許可"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"削除"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 3ddae4d..ea7ee74 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"რჩეულების თაროზე ადგილი არ არის"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"აპები"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"მთავარი"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"მოშორება"</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="permlab_install_shortcut" msgid="5632423390354674437">"მალსახმობების დაყენება"</string>
@@ -59,7 +59,7 @@
     <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_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები &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_opened" msgid="94695026776264709">"საქაღალდე გახსნილია, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"როტაციის დაშვება"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"უცნობი"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ამოშლა"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index eead791..5b31966 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -38,7 +38,7 @@
     <string name="all_apps_button_label" msgid="9110807029020582876">"Қолданбалар"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Негізгі"</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="permlab_install_shortcut" msgid="5632423390354674437">"төте пернелерді орнату"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді."</string>
@@ -69,8 +69,9 @@
     <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="wallpaper_button_text" msgid="8404103075899945851">"Артқы фондар"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Параметрлер"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Айналуға рұқсат ету"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Белгісіз"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Алып тастау"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index d6a1b0a..f49135b 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -60,7 +60,7 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"រូប​តំណាង​ច្បាប់​ចម្លង"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ចាប់ផ្ដើម​ធ្វើ​ឲ្យ​ស្រស់"</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_description" msgid="4119994475505235248">"ប៉ះ &amp; សង្កត់​ផ្ទៃ​ខាង​ក្រោយ​ដើម្បី​ប្ដូរ​តាម​​តម្រូវ​ការ"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"យល់​ហើយ"</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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"អនុញ្ញាតឲ្យបង្វិល"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"មិន​ស្គាល់"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"លុបចេញ"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 8766d71..48729d4 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"ತಿರುಗಿಸುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"ಅಜ್ಞಾತ"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index be5b506..aa5719f 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"회전 허용"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"삭제"</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 9b0ecfb..5d4c8a3 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -38,7 +38,7 @@
     <string name="all_apps_button_label" msgid="9110807029020582876">"Колдонмолор"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Үйгө"</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="permlab_install_shortcut" msgid="5632423390354674437">"тез чакырмаларды орнотуу"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет."</string>
@@ -59,8 +59,8 @@
     <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_longpress_title" msgid="9173998993909018310">"Тушкагаздар, виджеттер жана жөндөөлөр"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Өзгөчөлөштүрүү үчүн фонго тийип коё бербей басып туруңуз"</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_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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Айлантууга уруксат берүү"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Белгисиз"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Алып салуу"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 496aa2d..820f268 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -37,8 +37,8 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"ບໍ່ມີບ່ອນຫວ່າງໃນຖາດສຳລັບເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"ແອັບຯ"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"ໜ້າຫຼັກ"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"ລຶບອອກ"</string>
-    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ຖອນການຕິດຕັ້ງ"</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="permlab_install_shortcut" msgid="5632423390354674437">"ຕິດຕັ້ງທາງລັດ"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"ອະນຸຍາດໃຫ້ແອັບຯ ເພີ່ມທາງລັດໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້."</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"ອະ​ນຸ​ຍາດ​ການ​ໝຸນ"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"​ບໍ່​ຮູ້​ຈັກ"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ລຶບ​"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index f20751a..f9a1a09 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Išjungė administratorius"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Leisti kaitaliojimą"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Nežinoma"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Pašalinti"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 7e76374..d9b59ad 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Atspējojis administrators"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Rotācijas atļauja"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Nezināma"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Noņemt"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 37bd1cf..a1bf843 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -42,9 +42,9 @@
     <string name="info_target_label" msgid="8053346143994679532">"Информации за апликацијата"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирај кратенки"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Овозможува апликацијата да додава кратенки без интервенција на корисникот."</string>
-    <string name="permlab_read_settings" msgid="1941457408239617576">"чита поставки и кратенки на почетна страница"</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="permlab_write_settings" msgid="3574213698004620587">"напиши подесувања и кратенки на почетна страница"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> нема дозвола за телефонски повици"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Проблем при вчитувањето на виџетот"</string>
@@ -54,12 +54,12 @@
     <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="workspace_new_page" msgid="257366611030256142">"Нова страница на почетен екран"</string>
-    <string name="first_run_cling_title" msgid="2459738000155917941">"Добре дојдовте"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"Добредојдовте"</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_longpress_title" msgid="9173998993909018310">"Позадини, додатоци и поставки"</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_opened" msgid="94695026776264709">"Отворена е папка, <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
@@ -68,9 +68,10 @@
     <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="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Поставки"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволи ротација"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index e0e1801..cc6c7d7 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -38,7 +38,7 @@
     <string name="all_apps_button_label" msgid="9110807029020582876">"അപ്ലിക്കേഷനുകൾ"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"ഹോം"</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="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"തിരിക്കൽ അനുവദിക്കുക"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index 2c26714..0622600 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"\"Дуртай\" трей дээр өөр зай байхгүй байна"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"Апп"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"Нүүр"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"Хасах"</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="permlab_install_shortcut" msgid="5632423390354674437">"товчлол суулгах"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Таны админ идэвхгүй болгосон"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Эргүүлэхийг зөвшөөрөх"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Тодорхойгүй"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Устгах"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 5d29197..e9e561f 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"फिरविण्‍यास अनुमती द्या"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 5da4331..423cba4 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Dilumpuhkan oleh pentadbir anda"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Benarkan putaran"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Tidak diketahui"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Alih keluar"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index c995a69..fade6b8 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -24,7 +24,7 @@
     <string name="work_folder_name" msgid="3753320833950115786">"အလုပ်"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"အပ်ပလီကေးရှင်း မထည့်သွင်းထားပါ"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App လက်လှမ်း မမှီပါ"</string>
-    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ဒေါင်းလုဒ် အက်ပ်ကို လုံခြုံရေး မုဒ်ထဲမှာ ပိတ်ထား"</string>
+    <string name="safemode_shortcut_error" msgid="9160126848219158407">"ဒေါင်းလုဒ် appကို လုံခြုံရေး မုဒ်ထဲမှာ ပိတ်ထား"</string>
     <string name="safemode_widget_error" msgid="4863470563535682004">"လုံခြုံရေး မုဒ်ထဲမှာ ဝီဂျက်များကို ပိတ်ထား"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ဝဒ်ဂျက်တစ်ခုကို ကောက်ယူရန် ဖိနှိပ်ထားပါ"</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ဝစ်ဂျက်တစ်ခုကိုရယူရန် သို့မဟုတ် စိတ်ကြိုက်လုပ်ဆောင်မှုများကို အသုံးပြုရန် နှစ်ချက်တို့ပြီး ကိုင်ထားပါ။"</string>
@@ -35,10 +35,10 @@
     <string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g>ကို သွားပါ"</string>
     <string name="out_of_space" msgid="4691004494942118364">"ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"အနှစ်သက်ဆုံးများ ထားရာတွင် နေရာလွတ် မကျန်တော့ပါ"</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_target_label" msgid="1822697352535677073">"ဖယ်ရှားပါ"</string>
-    <string name="delete_target_uninstall_label" msgid="5100785476250872595">"ပြန်ထုတ်ပါ"</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="permlab_install_shortcut" msgid="5632423390354674437">"အတိုကောက်မှတ်သားမှုများအား ထည့်သွင်းခြင်း"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"အသုံးပြုသူ လုပ်ဆောင်မှုမရှိပဲ အပ်ပလီကေးရှင်းကို အတိုကောက်မှတ်သားမှုများ ပြုလုပ်ခွင့် ပေးခြင်း"</string>
@@ -59,24 +59,25 @@
     <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_longpress_title" msgid="9173998993909018310">"နောက်ခံများ၊ ဝိဂျက်များ&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="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ရပြီ"</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="widget_button_text" msgid="2880537293434387943">"ဝဒ်ဂျက်များ"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"နောက်ခံများ"</string>
-    <string name="settings_button_text" msgid="8119458837558863227">"ဆက်တင်များ"</string>
-    <string name="allow_rotation_title" msgid="2118706734511831751">"လှည့်နိုင်သည်"</string>
+    <string name="settings_button_text" msgid="8119458837558863227">"အပြင်အဆင်များ"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်"</string>
+    <string name="allow_rotation_title" msgid="2118706734511831751">"လှည့်ရန် ခွင့်ပြုမည်"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"မသိရ"</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">"ဤအိုင်ကွန်အတွက် အက်ပ် အားမထည့်သွင်းထားပါ။ You can remove it, or search for the အက်ပ် and install it manually."</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ဤအိုင်ကွန်အတွက် app အားမထည့်သွင်းထားပါ။ You can remove it, or search for the app and install it manually."</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ဒေါင်းလုဒ်လုပ်နေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ကိုထည့်သွင်းရန်စောင့်နေသည်"</string>
     <string name="action_add_to_workspace" msgid="8902165848117513641">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 7b5f3b6..934a5d0 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Administratoren har slått av funksjonen"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Tillat rotasjon"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Ukjent"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 007934c..f4f46d8 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -38,7 +38,7 @@
     <string name="all_apps_button_label" msgid="9110807029020582876">"अनुप्रयोगहरू"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"गृह"</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="permlab_install_shortcut" msgid="5632423390354674437">"सर्टकट स्थापना गर्नेहोस्"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
@@ -54,14 +54,14 @@
     <string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d को %1$d"</string>
     <string name="workspace_scroll_format" msgid="8458889198184077399">"गृह स्क्रिन %1$d को %2$d"</string>
     <string name="workspace_new_page" msgid="257366611030256142">"नयाँ गृह स्क्रिन पृष्ठ"</string>
-    <string name="first_run_cling_title" msgid="2459738000155917941">"स्वागतम्"</string>
+    <string name="first_run_cling_title" msgid="2459738000155917941">"स्वागतम"</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_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="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_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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"परिक्रमणलाई अनुमति दिनुहोस्"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 3f98106..58ab411 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -69,8 +69,9 @@
     <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="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
-    <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string>
+    <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergronden"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Instellingen"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Uitgeschakeld door je beheerder"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Draaien toestaan"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 1a10a73..ac976d4 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -25,13 +25,13 @@
     <string name="activity_not_found" msgid="8071924732094499514">"ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"ਡਾਊਨਲੋਡ ਕੀਤਾ ਐਪ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ"</string>
-    <string name="safemode_widget_error" msgid="4863470563535682004">"ਵਿਜਿਟ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"ਵਿਜੇਟਸ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਛੋਹਵੋT &amp; ਹੋਲਡ ਕਰੋ।"</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ਡਬਲ-ਟੈਪ &amp; ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਹੋਲਡ ਕਰੋ ਅਤੇ ਕਸਟਮ ਕਿਰਿਆਵਾਂ ਵਰਤੋ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"ਐਪਾਂ ਖੋਜੋ…"</string>
-    <string name="all_apps_loading_message" msgid="7557140873644765180">"ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
-    <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ਨਾਲ ਮਿਲਦੀਆਂ ਕੋਈ ਵੀ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ"</string>
+    <string name="all_apps_loading_message" msgid="7557140873644765180">"ਐਪਸ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ਨਾਲ ਮਿਲਦੀ ਕੋਈ ਵੀ ਐਪਸ ਨਹੀਂ ਲੱਭੀਆਂ"</string>
     <string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g> ਤੇ ਜਾਓ"</string>
     <string name="out_of_space" msgid="4691004494942118364">"ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਲਈ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।"</string>
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"ਮਨਪਸੰਦ ਟ੍ਰੇ ਵਿੱਚ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ।"</string>
@@ -40,15 +40,15 @@
     <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="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ਾਰਟਕੱਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
-    <string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</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="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ੌਰਟਕਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
+    <string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ੌਰਟਕਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</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="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਫੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"ਵਿਜੇਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ"</string>
-    <string name="gadget_setup_text" msgid="8274003207686040488">"ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="gadget_setup_text" msgid="8274003207686040488">"ਸੈਟਅਪ"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="folder_hint_text" msgid="6617836969016293992">"ਬਿਨਾਂ ਨਾਮ ਦਿੱਤਾ ਫੋਲਡਰ"</string>
     <string name="default_scroll_format" msgid="7475544710230993317">"ਸਫ਼ਾ %2$d ਦਾ %1$d"</string>
@@ -59,18 +59,19 @@
     <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_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="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_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_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="widget_button_text" msgid="2880537293434387943">"ਵਿਜੇਟਸ"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ਵਾਲਪੇਪਰ"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"ਰੋਟੇਸ਼ਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"ਅਗਿਆਤ"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index ab70265..43e4947 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Funkcja wyłączona przez administratora"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Zezwól na obrót"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Brak informacji"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Usuń"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 8a469ac..6338003 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo administrador"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotação"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 9ba9d6d..a8562a4 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotação"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 8c715f8..bc8b0ab 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Dezactivată de administrator"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Permiteți rotirea"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Necunoscut"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminați"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 8f2dc42..4a2cb61 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -60,7 +60,7 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРОВАТЬ ЗНАЧКИ"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"ИСПОЛЬЗОВАТЬ СТАНДАРТНЫЙ МАКЕТ"</string>
     <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Обои, виджеты и настройки"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Чтобы выполнить настройку, коснитесь фона и удерживайте его."</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Чтобы выполнить настройку, коснитесь фона и удерживайте его"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ОК"</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>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Разрешить автоповорот"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Неизвестно"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Удалить"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 1fd7df0..a072cee 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"ඔබගේ පරිපාලක විසින් අබල කරන ලදී"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"කරකැවීමට ඉඩ දෙන්න"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"නොදනී"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ඉවත් කරන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index cc3a2b4..5fb421a 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -29,10 +29,10 @@
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Miniaplikáciu pridáte stlačením a podržaním."</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Miniaplikáciu pridáte dvojitým klepnutím a pridržaním alebo pomocou vlastných akcií."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
-    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Hľadať aplikácie…"</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Vyhľadávanie v aplikáciách…"</string>
     <string name="all_apps_loading_message" msgid="7557140873644765180">"Načítavajú sa aplikácie..."</string>
     <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nenašli sa žiadne aplikácie zodpovedajúce dopytu <xliff:g id="QUERY">%1$s</xliff:g>"</string>
-    <string name="all_apps_search_market_message" msgid="5470761048755751471">"Prejsť na <xliff:g id="QUERY">%1$s</xliff:g>"</string>
+    <string name="all_apps_search_market_message" msgid="5470761048755751471">"Prejsť na dopyt <xliff:g id="QUERY">%1$s</xliff:g>"</string>
     <string name="out_of_space" msgid="4691004494942118364">"Na tejto ploche už nie je miesto"</string>
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"Na paneli Obľúbené položky už nie je miesto"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"Aplikácie"</string>
@@ -59,8 +59,8 @@
     <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Ť ODZNOVA"</string>
-    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Tapety, miniaplikácie a nastavenia"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pozadie môžete prispôsobiť jeho pridržaním"</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">"DOBRE"</string>
     <string name="folder_opened" msgid="94695026776264709">"Otvorený priečinok, <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">"Dotykom zavriete priečinok"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázané vaším správcom"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Povoliť otáčanie"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Neznáme"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrániť"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index d5e1e4f..57a89c7 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Omogočanje zasuka"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Neznano"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrani"</string>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index 6262170..a530ff9 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -71,6 +71,7 @@
     <string name="widget_button_text" msgid="2880537293434387943">"Miniaplikacionet"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Imazhet e sfondit"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Cilësimet"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Lejo rotacionin"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"I panjohur"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Hiq"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index f193909..cc3d6a2 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Администратор је онемогућио"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволи ротацију"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Уклони"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 10f5ce4..9eb5299 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Inaktiverat av administratören"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Tillåt rotering"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Okänt"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Ta bort"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 9e2b246..831d6ef 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -62,7 +62,7 @@
     <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_longpress_title" msgid="9173998993909018310">"Mandhari, wijeti na mipangilio"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Gusa na ushikilie mandhari ili ubadilishe upendavyo"</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_opened" msgid="94695026776264709">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
     <string name="folder_tap_to_close" msgid="1884479294466410023">"Gusa ili ufunge folda"</string>
@@ -73,6 +73,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Imezimwa na msimamizi wako"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Ruhusu kuzungusha"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Yasiyojulikana"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Ondoa"</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 3990286..ef1fee4 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"உங்கள் நிர்வாகி முடக்கியுள்ளார்"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"சுழற்ற அனுமதி"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"தெரியாதது"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"அகற்று"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index 997e198..c3a8cd4 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"భ్రమణాన్ని అనుమతించండి"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index b90599e..ead28d6 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"ปิดใช้โดยผู้ดูแลระบบ"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"อนุญาตให้ใช้การหมุน"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"ไม่รู้จัก"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ลบ"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 6b08c0e..c229355 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Na-disable ng iyong admin"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Payagan ang pag-rotate"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Hindi kilala"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Alisin"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 07db876..fc4a69f 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Yöneticiniz tarafından devre dışı bırakıldı"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Döndürmeye izin ver"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Bilinmiyor"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Kaldır"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 66f2542..9607099 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Вимкнув адміністратор"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволити обертання"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Невідомо"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Видалити"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index b3d4c29..e7ac4b3 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"گردش کی اجازت دیں"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"نامعلوم"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ہٹائیں"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index ce79900..fd71c41 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -29,14 +29,14 @@
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidjetni tanlash uchun bosib turing."</string>
     <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
-    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Ilovalar ichidan qidirish…"</string>
+    <string name="all_apps_search_bar_hint" msgid="6705987535534678581">"Ilovalarni qidirish…"</string>
     <string name="all_apps_loading_message" msgid="7557140873644765180">"Ilovalar yuklanmoqda…"</string>
-    <string name="all_apps_no_search_results" msgid="6332185285860416787">"“<xliff:g id="QUERY">%1$s</xliff:g>” so‘rovi bo‘yicha hech narsa topilmadi"</string>
-    <string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g>"</string>
+    <string name="all_apps_no_search_results" msgid="6332185285860416787">"“<xliff:g id="QUERY">%1$s</xliff:g>” bilan mos hech qanday ilova topilmadi"</string>
+    <string name="all_apps_search_market_message" msgid="5470761048755751471">"O‘tish: <xliff:g id="QUERY">%1$s</xliff:g>"</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="all_apps_button_label" msgid="9110807029020582876">"Ilovalar"</string>
-    <string name="all_apps_home_button_label" msgid="252062713717058851">"Bosh sahifa"</string>
+    <string name="all_apps_home_button_label" msgid="252062713717058851">"Uy"</string>
     <string name="delete_target_label" msgid="1822697352535677073">"Olib tashlash"</string>
     <string name="delete_target_uninstall_label" msgid="5100785476250872595">"O‘chirib tashlash"</string>
     <string name="info_target_label" msgid="8053346143994679532">"Ilova haqida"</string>
@@ -59,8 +59,8 @@
     <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_longpress_title" msgid="9173998993909018310">"Fon rasmlari, vidjet va sozlamalar"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Moslashtirish uchun orqa fon ustiga biroz bosib turing"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Orqa fon rasmlari, vidjet va sozlamalar"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Orqa fonni moslashtirish uchun uni bosing va ushlab turing"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"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>
@@ -71,7 +71,8 @@
     <string name="widget_button_text" msgid="2880537293434387943">"Vidjetlar"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Fon rasmlari"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"Sozlamalar"</string>
-    <string name="allow_rotation_title" msgid="2118706734511831751">"Avtomatik burilish"</string>
+    <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator tomonidan o‘chirilgan"</string>
+    <string name="allow_rotation_title" msgid="2118706734511831751">"Aylanishga ruxsat berish"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Noma’lum"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"O‘chirish"</string>
     <string name="abandoned_search" msgid="891119232568284442">"Qidirish"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 1ecc92e..40947bd 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Bị tắt bởi quản trị viên của bạn"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Cho phép xoay"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Xóa"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 72b6ec7..e333ecb 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -37,7 +37,7 @@
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"收藏栏已满"</string>
     <string name="all_apps_button_label" msgid="9110807029020582876">"应用"</string>
     <string name="all_apps_home_button_label" msgid="252062713717058851">"主屏幕"</string>
-    <string name="delete_target_label" msgid="1822697352535677073">"移除"</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="permlab_install_shortcut" msgid="5632423390354674437">"安装快捷方式"</string>
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"已被您的管理员停用"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"允许旋转"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"未知"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 41679b5..b65630e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"允許旋轉"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index bc3be0c..1c954fd 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"允許輪播"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index a1dec74..af80b6c 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -71,6 +71,7 @@
     <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="msg_disabled_by_admin" msgid="6898038085516271325">"Kukhutshazwe umlawuli wakho"</string>
     <string name="allow_rotation_title" msgid="2118706734511831751">"Vumela ukuphenduka"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Akwaziwa"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Susa"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2838a22..630e3cd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -170,6 +170,8 @@
     <string name="wallpaper_button_text">Wallpapers</string>
     <!-- Text for settings button -->
     <string name="settings_button_text">Settings</string>
+    <!-- Message shown when a feature is disabled by the administrator -->
+    <string name="msg_disabled_by_admin">Disabled by your admin</string>
 
     <!-- Strings for settings -->
     <!-- Title for Allow Rotation setting. [CHAR LIMIT=50] -->
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 3b25dca..c431593 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -22,6 +22,8 @@
 import com.android.launcher3.compat.LauncherActivityInfoCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.FlagOp;
+import com.android.launcher3.util.StringFilter;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -118,6 +120,21 @@
         }
     }
 
+    /**
+     * Updates the apps for the given packageName and user based on {@param op}.
+     */
+    public void updatePackageFlags(StringFilter pkgFilter, UserHandleCompat user, FlagOp op) {
+        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 (info.user.equals(user) && pkgFilter.matches(component.getPackageName())) {
+                info.isDisabled = op.apply(info.isDisabled);
+                modified.add(info);
+            }
+        }
+    }
+
     public void updateIconsAndLabels(HashSet<String> packages, UserHandleCompat user,
             ArrayList<AppInfo> outUpdates) {
         for (AppInfo info : data) {
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index ede6c71..c7a6ae4 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -26,6 +26,7 @@
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.compat.UserManagerCompat;
 import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.PackageManagerHelper;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -58,6 +59,11 @@
 
     int flags = 0;
 
+    /**
+     * {@see ShortcutInfo#isDisabled}
+     */
+    int isDisabled = ShortcutInfo.DEFAULT;
+
     AppInfo() {
         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
     }
@@ -75,10 +81,22 @@
      */
     public AppInfo(Context context, LauncherActivityInfoCompat info, UserHandleCompat user,
             IconCache iconCache) {
+        this(context, info, user, iconCache,
+                UserManagerCompat.getInstance(context).isQuietModeEnabled(user));
+    }
+
+    public AppInfo(Context context, LauncherActivityInfoCompat info, UserHandleCompat user,
+            IconCache iconCache, boolean quietModeEnabled) {
         this.componentName = info.getComponentName();
         this.container = ItemInfo.NO_ID;
-
         flags = initFlags(info);
+        if (PackageManagerHelper.isAppSuspended(info.getApplicationInfo())) {
+            isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+        }
+        if (quietModeEnabled) {
+            isDisabled |= ShortcutInfo.FLAG_DISABLED_QUIET_USER;
+        }
+
         iconCache.getTitleAndIcon(this, info, true /* useLowResIcon */);
         intent = makeLaunchIntent(context, info, user);
         this.user = user;
@@ -103,6 +121,7 @@
         title = Utilities.trim(info.title);
         intent = new Intent(info.intent);
         flags = info.flags;
+        isDisabled = info.isDisabled;
         iconBitmap = info.iconBitmap;
     }
 
@@ -143,4 +162,9 @@
             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
             .putExtra(EXTRA_PROFILE, serialNumber);
     }
+
+    @Override
+    public boolean isDisabled() {
+        return isDisabled != 0;
+    }
 }
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index f6c9e3c..09ec60c 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -150,7 +150,7 @@
         Bitmap b = info.getIcon(iconCache);
 
         FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(b);
-        if (info.isDisabled != 0) {
+        if (info.isDisabled()) {
             iconDrawable.setState(FastBitmapDrawable.State.DISABLED);
         }
         setIcon(iconDrawable, mIconSize);
@@ -166,7 +166,11 @@
     }
 
     public void applyFromApplicationInfo(AppInfo info) {
-        setIcon(mLauncher.createIconDrawable(info.iconBitmap), mIconSize);
+        FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(info.iconBitmap);
+        if (info.isDisabled()) {
+            iconDrawable.setState(FastBitmapDrawable.State.DISABLED);
+        }
+        setIcon(iconDrawable, mIconSize);
         setText(info.title);
         if (info.contentDescription != null) {
             setContentDescription(info.contentDescription);
@@ -250,11 +254,11 @@
     private void updateIconState() {
         if (mIcon instanceof FastBitmapDrawable) {
             FastBitmapDrawable d = (FastBitmapDrawable) mIcon;
-            if (isPressed() || mStayPressed) {
-                d.animateState(FastBitmapDrawable.State.PRESSED);
-            } else if (getTag() instanceof ShortcutInfo
-                    && ((ShortcutInfo) getTag()).isDisabled != 0) {
+            if (getTag() instanceof ItemInfo
+                    && ((ItemInfo) getTag()).isDisabled()) {
                 d.animateState(FastBitmapDrawable.State.DISABLED);
+            } else if (isPressed() || mStayPressed) {
+                d.animateState(FastBitmapDrawable.State.PRESSED);
             } else {
                 d.animateState(FastBitmapDrawable.State.NORMAL);
             }
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index eefb287..2f0bfe5 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -341,7 +341,8 @@
         }
         endDrag();
     }
-    public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) {
+
+    public void onAppsRemoved(final HashSet<String> packageNames, HashSet<ComponentName> cns) {
         // Cancel the current drag if we are removing an app that we are dragging
         if (mDragObject != null) {
             Object rawDragInfo = mDragObject.dragInfo;
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index ad9063c..9886c3f 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -95,8 +95,6 @@
     private Drawable mLeftHoverDrawableActive;
     private Drawable mRightHoverDrawableActive;
 
-    private boolean mBlockTouches = false;
-
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -166,19 +164,11 @@
         return false;
     }
 
-    public void setBlockTouch(boolean block) {
-        mBlockTouches = block;
-    }
-
     private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
         Rect hitRect = new Rect();
         int x = (int) ev.getX();
         int y = (int) ev.getY();
 
-        if (mBlockTouches) {
-            return true;
-        }
-
         for (AppWidgetResizeFrame child: mResizeFrames) {
             child.getHitRect(hitRect);
             if (hitRect.contains(x, y)) {
@@ -343,10 +333,6 @@
         int x = (int) ev.getX();
         int y = (int) ev.getY();
 
-        if (mBlockTouches) {
-            return true;
-        }
-
         if (action == MotionEvent.ACTION_DOWN) {
             if (handleTouchDown(ev, false)) {
                 return true;
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 471c324..b43d965 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -208,8 +208,26 @@
         });
         mFolderName.setOnFocusChangeListener(this);
 
-        // We disable action mode for now since it messes up the view on phones
-        mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
+        if (!Utilities.ATLEAST_MARSHMALLOW) {
+            // We disable action mode in older OSes where floating selection menu is not yet
+            // available.
+            mFolderName.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
+                public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+                    return false;
+                }
+
+                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+                    return false;
+                }
+
+                public void onDestroyActionMode(ActionMode mode) {
+                }
+
+                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                    return false;
+                }
+            });
+        }
         mFolderName.setOnEditorActionListener(this);
         mFolderName.setSelectAllOnFocus(true);
         mFolderName.setInputType(mFolderName.getInputType() |
@@ -224,23 +242,6 @@
         mFooterHeight = mFooter.getMeasuredHeight();
     }
 
-    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
-        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            return false;
-        }
-
-        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-            return false;
-        }
-
-        public void onDestroyActionMode(ActionMode mode) {
-        }
-
-        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-            return false;
-        }
-    };
-
     public void onClick(View v) {
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 05ad538..c72c2f9 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -118,7 +118,7 @@
         mUserManager = UserManagerCompat.getInstance(mContext);
         mLauncherApps = LauncherAppsCompat.getInstance(mContext);
         mIconDpi = inv.fillResIconDpi;
-        mIconDb = new IconDB(context);
+        mIconDb = new IconDB(context, inv.iconBitmapSize);
 
         mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
 
@@ -809,8 +809,10 @@
         private final static String COLUMN_LABEL = "label";
         private final static String COLUMN_SYSTEM_STATE = "system_state";
 
-        public IconDB(Context context) {
-            super(context, LauncherFiles.APP_ICONS_DB, RELEASE_VERSION, TABLE_NAME);
+        public IconDB(Context context, int iconPixelSize) {
+            super(context, LauncherFiles.APP_ICONS_DB,
+                    (RELEASE_VERSION << 16) + iconPixelSize,
+                    TABLE_NAME);
         }
 
         @Override
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 46b9b7d..921e90c 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -87,7 +87,7 @@
         }
     }
 
-    public static void removeFromInstallQueue(Context context, ArrayList<String> packageNames,
+    public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
             UserHandleCompat user) {
         if (packageNames.isEmpty()) {
             return;
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index b3a8bbc..d601322 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -73,17 +73,17 @@
     /**
      * Number of icons inside the hotseat area.
      */
-    int numHotseatIcons;
+    public int numHotseatIcons;
     float hotseatIconSize;
     int defaultLayoutId;
 
     // Derived invariant properties
-    int hotseatAllAppsRank;
+    public int hotseatAllAppsRank;
 
     DeviceProfile landscapeProfile;
     DeviceProfile portraitProfile;
 
-    InvariantDeviceProfile() {
+    public InvariantDeviceProfile() {
     }
 
     public InvariantDeviceProfile(InvariantDeviceProfile p) {
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index f7e0ea4..c7a6807 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -197,4 +197,11 @@
             + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
             + " user=" + user + ")";
     }
+
+    /**
+     * Whether this item is disabled.
+     */
+    public boolean isDisabled() {
+        return false;
+    }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 166acd3..23a5739 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -216,10 +216,6 @@
 
     private boolean mIsSafeModeEnabled;
 
-    LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl();
-    LauncherOverlay mLauncherOverlay;
-    InsettableFrameLayout mLauncherOverlayContainer;
-
     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;
@@ -488,11 +484,11 @@
         IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         registerReceiver(mCloseSystemDialogsReceiver, filter);
 
-        mRotationEnabled = Utilities.isRotationAllowedForDevice(getApplicationContext());
+        mRotationEnabled = getResources().getBoolean(R.bool.allow_rotation);
         // In case we are on a device with locked rotation, we should look at preferences to check
         // if the user has specifically allowed rotation.
         if (!mRotationEnabled) {
-            mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext(), false);
+            mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext());
         }
 
         // On large interfaces, or on devices that a user has specifically enabled screen rotation,
@@ -501,13 +497,6 @@
 
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onCreate(savedInstanceState);
-            if (mLauncherCallbacks.hasLauncherOverlay()) {
-                ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub);
-                mLauncherOverlayContainer = (InsettableFrameLayout) stub.inflate();
-                mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(
-                        mLauncherOverlayContainer, mLauncherOverlayCallbacks);
-                mWorkspace.setLauncherOverlay(mLauncherOverlay);
-            }
         }
 
         if (shouldShowIntroScreen()) {
@@ -537,6 +526,16 @@
         }
     }
 
+    /**
+     * Call this after onCreate to set or clear overlay.
+     */
+    public void setLauncherOverlay(LauncherOverlay overlay) {
+        if (overlay != null) {
+            overlay.setOverlayCallbacks(new LauncherOverlayCallbacksImpl());
+        }
+        mWorkspace.setLauncherOverlay(overlay);
+    }
+
     public boolean setLauncherCallbacks(LauncherCallbacks callbacks) {
         mLauncherCallbacks = callbacks;
         mLauncherCallbacks.setLauncherSearchCallback(new Launcher.LauncherSearchCallbacks() {
@@ -856,7 +855,7 @@
             sPendingAddItem = null;
             if (grantResults.length > 0
                     && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                startActivity(v, intent, null);
+                startActivitySafely(v, intent, null);
             } else {
                 // TODO: Show a snack bar with link to settings
                 Toast.makeText(this, getString(R.string.msg_no_phone_permission,
@@ -889,8 +888,7 @@
      * @return the new screen, or screenId if it exists
      */
     private long ensurePendingDropLayoutExists(long screenId) {
-        CellLayout dropLayout =
-                (CellLayout) mWorkspace.getScreenWithId(screenId);
+        CellLayout dropLayout = mWorkspace.getScreenWithId(screenId);
         if (dropLayout == null) {
             // it's possible that the add screen was removed because it was
             // empty and a re-bind occurred
@@ -1125,18 +1123,13 @@
          * Scroll progress, between 0 and 100, when the user scrolls beyond the leftmost
          * screen (or in the case of RTL, the rightmost screen).
          */
-        public void onScrollChange(int progress, boolean rtl);
+        public void onScrollChange(float progress, boolean rtl);
 
         /**
-         * Screen has stopped scrolling
+         * Called when the launcher is ready to use the overlay
+         * @param callbacks A set of callbacks provided by Launcher in relation to the overlay
          */
-        public void onScrollSettled();
-
-        /**
-         * This method can be called by the Launcher in order to force the LauncherOverlay
-         * to exit fully immersive mode.
-         */
-        public void forceExitFullImmersion();
+        public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks);
     }
 
     public interface LauncherSearchCallbacks {
@@ -1152,50 +1145,15 @@
     }
 
     public interface LauncherOverlayCallbacks {
-        /**
-         * This method indicates whether a call to {@link #enterFullImmersion()} will succeed,
-         * however it doesn't modify any state within the launcher.
-         */
-        public boolean canEnterFullImmersion();
-
-        /**
-         * Should be called to tell Launcher that the LauncherOverlay will take over interaction,
-         * eg. by occupying the full screen and handling all touch events.
-         *
-         * @return true if Launcher allows the LauncherOverlay to become fully immersive. In this
-         *          case, Launcher will modify any necessary state and assumes the overlay is
-         *          handling all interaction. If false, the LauncherOverlay should cancel any
-         *
-         */
-        public boolean enterFullImmersion();
-
-        /**
-         * Must be called when exiting fully immersive mode. Indicates to Launcher that it has
-         * full control over UI and state.
-         */
-        public void exitFullImmersion();
+        public void onScrollChanged(float progress);
     }
 
     class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks {
 
-        @Override
-        public boolean canEnterFullImmersion() {
-            return mState == State.WORKSPACE;
-        }
-
-        @Override
-        public boolean enterFullImmersion() {
-            if (mState == State.WORKSPACE) {
-                // When fully immersed, disregard any touches which fall through.
-                mDragLayer.setBlockTouch(true);
-                return true;
+        public void onScrollChanged(float progress) {
+            if (mWorkspace != null) {
+                mWorkspace.onOverlayScrollChanged(progress);
             }
-            return false;
-        }
-
-        @Override
-        public void exitFullImmersion() {
-            mDragLayer.setBlockTouch(false);
         }
     }
 
@@ -1205,7 +1163,7 @@
         } else {
             // On devices with a locked orientation, we will at least have the allow rotation
             // setting.
-            return !Utilities.isRotationAllowedForDevice(this);
+            return !getResources().getBoolean(R.bool.allow_rotation);
         }
     }
 
@@ -1378,8 +1336,9 @@
         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);
+        mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         mWorkspaceBackgroundDrawable = getResources().getDrawable(R.drawable.workspace_bg);
 
         // Setup the drag layer
@@ -1594,8 +1553,7 @@
 
         ItemInfo info = mPendingAddInfo;
         if (appWidgetInfo == null) {
-            appWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(this,
-                    mAppWidgetManager.getAppWidgetInfo(appWidgetId));
+            appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
         }
 
         if (appWidgetInfo.isCustomWidget) {
@@ -1695,6 +1653,10 @@
         FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
         mAttached = true;
         mVisible = true;
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onAttachedToWindow();
+        }
     }
 
     @Override
@@ -1707,6 +1669,10 @@
             mAttached = false;
         }
         updateAutoAdvanceState();
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onDetachedFromWindow();
+        }
     }
 
     public void onWindowVisibilityChanged(int visibility) {
@@ -1972,6 +1938,15 @@
 
     @Override
     protected void onSaveInstanceState(Bundle outState) {
+        // Catches the case where our activity is created and immediately destroyed and our views
+        // are not yet fully bound. In this case, we can't trust the state of our activity and
+        // instead save our previous state (which hasn't yet been consumed / applied, a fact we
+        // know as it's not null)
+        if (isWorkspaceLoading() && mSavedState != null) {
+            outState.putAll(mSavedState);
+            return;
+        }
+
         if (mWorkspace.getChildCount() > 0) {
             outState.putInt(RUNTIME_STATE_CURRENT_SCREEN,
                     mWorkspace.getCurrentPageOffsetFromCustomContent());
@@ -2591,10 +2566,10 @@
         final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
         if (v.isReadyForClickSetup()) {
             int widgetId = info.appWidgetId;
-            AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
+            LauncherAppWidgetProviderInfo appWidgetInfo =
+                    mAppWidgetManager.getLauncherAppWidgetInfo(widgetId);
             if (appWidgetInfo != null) {
-                mPendingAddWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(
-                        this, appWidgetInfo);
+                mPendingAddWidgetInfo = appWidgetInfo;
                 mPendingAddInfo.copyFrom(info);
                 mPendingAddWidgetId = widgetId;
 
@@ -2676,12 +2651,17 @@
         final ShortcutInfo shortcut = (ShortcutInfo) tag;
 
         if (shortcut.isDisabled != 0) {
-            int error = R.string.activity_not_available;
-            if ((shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_SAFEMODE) != 0) {
-                error = R.string.safemode_shortcut_error;
+            if ((shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_SUSPENDED) != 0
+                || (shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_QUIET_USER) != 0) {
+                // Launch activity anyway, framework will tell the user why the app is suspended.
+            } else {
+                int error = R.string.activity_not_available;
+                if ((shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_SAFEMODE) != 0) {
+                    error = R.string.safemode_shortcut_error;
+                }
+                Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
+                return;
             }
-            Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
-            return;
         }
 
         // Check for abandoned promise
@@ -2805,6 +2785,11 @@
      * on the home screen.
      */
     protected void onClickWallpaperPicker(View v) {
+        if (!Utilities.isWallapaperAllowed(this)) {
+            Toast.makeText(this, R.string.msg_disabled_by_admin, Toast.LENGTH_SHORT).show();
+            return;
+        }
+
         if (LOGD) Log.d(TAG, "onClickWallpaperPicker");
         int pageScroll = mWorkspace.getScrollForPage(mWorkspace.getPageNearestToCenterOfScreen());
         float offset = mWorkspace.mWallpaperOffset.wallpaperOffsetForScroll(pageScroll);
@@ -2982,8 +2967,18 @@
             }
 
             if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
-                // Could be launching some bookkeeping activity
-                startActivity(intent, optsBundle);
+                StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
+                try {
+                    // Temporarily disable deathPenalty on all default checks. For eg, shortcuts
+                    // containing file Uris would cause a crash as penaltyDeathOnFileUriExposure
+                    // is enabled by default on NYC.
+                    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
+                            .penaltyLog().build());
+                    // Could be launching some bookkeeping activity
+                    startActivity(intent, optsBundle);
+                } finally {
+                    StrictMode.setVmPolicy(oldPolicy);
+                }
             } else {
                 // TODO Component can be null when shortcuts are supported for secondary user
                 launcherApps.startActivityForProfile(intent.getComponent(), user,
@@ -3107,10 +3102,6 @@
         }
         oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
         oa.start();
-        if (Utilities.isPowerSaverOn(this)) {
-            // Animations are disabled in battery saver mode, so just skip to the end state.
-            oa.end();
-        }
     }
 
     private void shrinkAndFadeInFolderIcon(final FolderIcon fi, boolean animate) {
@@ -3588,10 +3579,6 @@
         // TODO
     }
 
-    protected void disableVoiceButtonProxy(boolean disable) {
-        // NO-OP
-    }
-
     public boolean launcherCallbacksProvidesSearch() {
         return (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch());
     }
@@ -3997,6 +3984,16 @@
         sFolders = folders.clone();
     }
 
+    private void bindSafeModeWidget(LauncherAppWidgetInfo item) {
+        PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, true);
+        view.updateIcon(mIconCache);
+        item.hostView = view;
+        item.hostView.updateAppWidget(null);
+        item.hostView.setOnClickListener(this);
+        addAppWidgetToWorkspace(item, null, false);
+        mWorkspace.requestLayout();
+    }
+
     /**
      * Add the views for a widget to the workspace.
      *
@@ -4012,19 +4009,31 @@
             return;
         }
 
+        if (mIsSafeModeEnabled) {
+            bindSafeModeWidget(item);
+            return;
+        }
+
         final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
         if (DEBUG_WIDGETS) {
             Log.d(TAG, "bindAppWidget: " + item);
         }
-        final Workspace workspace = mWorkspace;
 
-        LauncherAppWidgetProviderInfo appWidgetInfo =
-                LauncherModel.getProviderInfo(this, item.providerName, item.user);
+        final LauncherAppWidgetProviderInfo appWidgetInfo;
 
-        if (!mIsSafeModeEnabled
-                && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0)
-                && (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
+        if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
+            // If the provider is not ready, bind as a pending widget.
+            appWidgetInfo = null;
+        } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
+            // The widget id is not valid. Try to find the widget based on the provider info.
+            appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user);
+        } else {
+            appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId);
+        }
 
+        // If the provider is ready, but the width is not yet restored, try to restore it.
+        if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) &&
+                (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
             if (appWidgetInfo == null) {
                 if (DEBUG_WIDGETS) {
                     Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
@@ -4036,7 +4045,7 @@
             }
 
             // If we do not have a valid id, try to bind an id.
-            if ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0) {
+            if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
                 // 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.
@@ -4072,46 +4081,42 @@
                         : LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
 
                 LauncherModel.updateItemInDatabase(this, item);
-            } else if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0)
+            } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
                     && (appWidgetInfo.configure == null)) {
-                // If the ID is already valid, verify if we need to configure or not.
+                // The widget was marked as UI not ready, but there is no configure activity to
+                // update the UI.
                 item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                 LauncherModel.updateItemInDatabase(this, item);
             }
         }
 
-        if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
-            final int appWidgetId = item.appWidgetId;
+        if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
             if (DEBUG_WIDGETS) {
                 Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component "
                         + appWidgetInfo.provider);
             }
 
             // Verify that we own the widget
-            AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
-            if (info == null || appWidgetInfo == null ||
-                    !info.provider.equals(appWidgetInfo.provider)) {
-                Log.e(TAG, "Removing invalid widget: id=" + item.appWidgetId + " info=" + info
-                        + " appWidgetInfo=" + appWidgetInfo);
+            if (appWidgetInfo == null) {
+                Log.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
                 deleteWidgetInfo(item);
                 return;
             }
 
-            item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+            item.hostView = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
             item.minSpanX = appWidgetInfo.minSpanX;
             item.minSpanY = appWidgetInfo.minSpanY;
+            addAppWidgetToWorkspace(item, appWidgetInfo, false);
         } else {
-            appWidgetInfo = null;
             PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item,
                     mIsSafeModeEnabled);
             view.updateIcon(mIconCache);
             item.hostView = view;
             item.hostView.updateAppWidget(null);
             item.hostView.setOnClickListener(this);
+            addAppWidgetToWorkspace(item, null, false);
         }
-
-        addAppWidgetToWorkspace(item, appWidgetInfo, false);
-        workspace.requestLayout();
+        mWorkspace.requestLayout();
 
         if (DEBUG_WIDGETS) {
             Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
@@ -4348,7 +4353,7 @@
             }
             mWorkspace.removeItemsByComponentName(removedComponents, user);
             // Notify the drag controller
-            mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents);
+            mDragController.onAppsRemoved(new HashSet<String>(), removedComponents);
         }
     }
 
@@ -4372,43 +4377,44 @@
     }
 
     /**
-     * A package was uninstalled.  We take both the super set of packageNames
+     * A package was uninstalled/updated.  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,
-     * we only remove specific components from the workspace, where as
+     * we only remove specific components from the workspace and hotseat, where as
      * package-removal should clear all items by package name.
-     *
-     * @param reason if non-zero, the icons are not permanently removed, rather marked as disabled.
-     * Implementation of the method from LauncherModel.Callbacks.
      */
     @Override
-    public void bindComponentsRemoved(final ArrayList<String> packageNames,
-            final ArrayList<AppInfo> appInfos, final UserHandleCompat user, final int reason) {
+    public void bindWorkspaceComponentsRemoved(
+            final HashSet<String> packageNames, final HashSet<ComponentName> components,
+            final UserHandleCompat user) {
         Runnable r = new Runnable() {
             public void run() {
-                bindComponentsRemoved(packageNames, appInfos, user, reason);
+                bindWorkspaceComponentsRemoved(packageNames, components, user);
             }
         };
         if (waitUntilResume(r)) {
             return;
         }
+        if (!packageNames.isEmpty()) {
+            mWorkspace.removeItemsByPackageName(packageNames, user);
+        }
+        if (!components.isEmpty()) {
+            mWorkspace.removeItemsByComponentName(components, user);
+        }
+        // Notify the drag controller
+        mDragController.onAppsRemoved(packageNames, components);
 
-        if (reason == 0) {
-            HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
-            for (AppInfo info : appInfos) {
-                removedComponents.add(info.componentName);
-            }
-            if (!packageNames.isEmpty()) {
-                mWorkspace.removeItemsByPackageName(packageNames, user);
-            }
-            if (!removedComponents.isEmpty()) {
-                mWorkspace.removeItemsByComponentName(removedComponents, user);
-            }
-            // Notify the drag controller
-            mDragController.onAppsRemoved(packageNames, removedComponents);
+    }
 
-        } else {
-            mWorkspace.disableShortcutsByPackageName(packageNames, user, reason);
+    @Override
+    public void bindAppInfosRemoved(final ArrayList<AppInfo> appInfos) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindAppInfosRemoved(appInfos);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
         }
 
         // Update AllApps
@@ -4417,15 +4423,15 @@
         }
     }
 
-    private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
+    private Runnable mBindWidgetModelRunnable = new Runnable() {
             public void run() {
-                bindAllPackages(mWidgetsModel);
+                bindWidgetsModel(mWidgetsModel);
             }
         };
 
     @Override
-    public void bindAllPackages(final WidgetsModel model) {
-        if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
+    public void bindWidgetsModel(WidgetsModel model) {
+        if (waitUntilResume(mBindWidgetModelRunnable, true)) {
             mWidgetsModel = model;
             return;
         }
@@ -4436,6 +4442,13 @@
         }
     }
 
+    @Override
+    public void notifyWidgetProvidersChanged() {
+        if (mWorkspace != null && mWorkspace.getState().shouldUpdateWidget) {
+            mModel.refreshAndBindWidgetsAndShortcuts(this, mWidgetsView.isEmpty());
+        }
+    }
+
     private int mapConfigurationOriActivityInfoOri(int configOri) {
         final Display d = getWindowManager().getDefaultDisplay();
         int naturalOri = Configuration.ORIENTATION_LANDSCAPE;
@@ -4608,9 +4621,6 @@
         if (introScreen != null) {
             mDragLayer.showOverlayView(introScreen);
         }
-        if (mLauncherOverlayContainer != null) {
-            mLauncherOverlayContainer.setVisibility(View.INVISIBLE);
-        }
     }
 
     public void dismissIntroScreen() {
@@ -4622,17 +4632,11 @@
                 @Override
                 public void run() {
                     mDragLayer.dismissOverlayView();
-                    if (mLauncherOverlayContainer != null) {
-                        mLauncherOverlayContainer.setVisibility(View.VISIBLE);
-                    }
                     showFirstRunClings();
                 }
             }, ACTIVITY_START_DELAY);
         } else {
             mDragLayer.dismissOverlayView();
-            if (mLauncherOverlayContainer != null) {
-                mLauncherOverlayContainer.setVisibility(View.VISIBLE);
-            }
             showFirstRunClings();
         }
         changeWallpaperVisiblity(true);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 5271029..e1ade10 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -100,6 +100,8 @@
         // For handling managed profiles
         filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED);
         filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED);
+        filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_AVAILABLE);
+        filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_UNAVAILABLE);
 
         sContext.registerReceiver(mModel, filter);
         UserManagerCompat.getInstance(sContext).enableAndResetCache();
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index b07ccc3..8c23ff3 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -102,6 +102,10 @@
                 callback.run();
             }
         }
+
+        if (Utilities.ATLEAST_MARSHMALLOW) {
+            mLauncher.notifyWidgetProvidersChanged();
+        }
     }
 
     public AppWidgetHostView createView(Context context, int appWidgetId,
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 4185257..0271089 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -251,7 +251,7 @@
     @Override
     public void requestChildFocus(View child, View focused) {
         super.requestChildFocus(child, focused);
-        dispatchChildFocus(focused != null);
+        dispatchChildFocus(mChildrenFocused && focused != null);
         if (focused != null) {
             focused.setFocusableInTouchMode(false);
         }
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 2177f52..1703e41 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -25,7 +25,7 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
-import com.android.launcher3.model.MigrateFromRestoreTask;
+import com.android.launcher3.model.GridSizeMigrationTask;
 
 import java.io.IOException;
 
@@ -118,11 +118,9 @@
                 LauncherAppState.getLauncherProvider().updateFolderItemsRank();
             }
 
-            if (MigrateFromRestoreTask.ENABLED && mHelper.shouldAttemptWorkspaceMigration()) {
-                MigrateFromRestoreTask.markForMigration(getApplicationContext(),
-                        (int) mHelper.migrationCompatibleProfileData.desktopCols,
-                        (int) mHelper.migrationCompatibleProfileData.desktopRows,
-                        mHelper.widgetSizes);
+            if (GridSizeMigrationTask.ENABLED && mHelper.shouldAttemptWorkspaceMigration()) {
+                GridSizeMigrationTask.markForMigration(getApplicationContext(),
+                        mHelper.widgetSizes, mHelper.migrationCompatibleProfileData);
             }
 
             LauncherAppState.getLauncherProvider().convertShortcutsToLauncherActivities();
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 47d1ce9..cad0f2c 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -50,9 +50,10 @@
 import com.android.launcher3.backup.nano.BackupProtos.Resource;
 import com.android.launcher3.backup.nano.BackupProtos.Screen;
 import com.android.launcher3.backup.nano.BackupProtos.Widget;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.model.MigrateFromRestoreTask;
+import com.android.launcher3.model.GridSizeMigrationTask;
 import com.android.launcher3.util.Thunk;
 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
 import com.google.protobuf.nano.MessageNano;
@@ -315,14 +316,13 @@
             return true;
         }
 
-        if (MigrateFromRestoreTask.ENABLED &&
-                (oldProfile.desktopCols - currentProfile.desktopCols <= 1) &&
-                (oldProfile.desktopRows - currentProfile.desktopRows <= 1)) {
-            // Allow desktop migration when row and/or column count contracts by 1.
-
+        if (GridSizeMigrationTask.ENABLED) {
+            // One time migrate the workspace when launcher starts.
             migrationCompatibleProfileData = initDeviceProfileData(mIdp);
             migrationCompatibleProfileData.desktopCols = oldProfile.desktopCols;
             migrationCompatibleProfileData.desktopRows = oldProfile.desktopRows;
+            migrationCompatibleProfileData.hotseatCount = oldProfile.hotseatCount;
+            migrationCompatibleProfileData.allappsRank = oldProfile.allappsRank;
             return true;
         }
         return false;
@@ -661,12 +661,14 @@
                 + getUserSelectionArg();
         Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
                 where, null, null);
+        AppWidgetManagerCompat widgetManager = AppWidgetManagerCompat.getInstance(mContext);
         try {
             cursor.moveToPosition(-1);
             while(cursor.moveToNext()) {
                 final long id = cursor.getLong(ID_INDEX);
                 final String providerName = cursor.getString(APPWIDGET_PROVIDER_INDEX);
                 final ComponentName provider = ComponentName.unflattenFromString(providerName);
+
                 Key key = null;
                 String backupKey = null;
                 if (provider != null) {
@@ -685,11 +687,14 @@
                 } else if (backupKey != null) {
                     if (DEBUG) Log.d(TAG, "I can count this high: " + backupWidgetCount);
                     if (backupWidgetCount < MAX_WIDGETS_PER_PASS) {
-                        if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
-                        UserHandleCompat user = UserHandleCompat.myUserHandle();
-                        writeRowToBackup(key, packWidget(dpi, provider, user), data);
-                        mKeys.add(key);
-                        backupWidgetCount ++;
+                        LauncherAppWidgetProviderInfo widgetInfo = widgetManager
+                                .getLauncherAppWidgetInfo(cursor.getInt(APPWIDGET_ID_INDEX));
+                        if (widgetInfo != null) {
+                            if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
+                            writeRowToBackup(key, packWidget(dpi, widgetInfo), data);
+                            mKeys.add(key);
+                            backupWidgetCount ++;
+                        }
                     } else {
                         if (VERBOSE) Log.v(TAG, "deferring widget backup " + backupKey);
                         // too many widgets for this pass, request another.
@@ -1005,16 +1010,14 @@
     }
 
     /** Serialize a widget for persistence, including a checksum wrapper. */
-    private Widget packWidget(int dpi, ComponentName provider, UserHandleCompat user) {
-        final LauncherAppWidgetProviderInfo info =
-                LauncherModel.getProviderInfo(mContext, provider, user);
+    private Widget packWidget(int dpi, LauncherAppWidgetProviderInfo info) {
         Widget widget = new Widget();
-        widget.provider = provider.flattenToShortString();
+        widget.provider = info.provider.flattenToShortString();
         widget.label = info.label;
         widget.configure = info.configure != null;
         if (info.icon != 0) {
             widget.icon = new Resource();
-            Drawable fullResIcon = mIconCache.getFullResIcon(provider.getPackageName(), info.icon);
+            Drawable fullResIcon = mIconCache.getFullResIcon(info.provider.getPackageName(), info.icon);
             Bitmap icon = Utilities.createIconBitmap(fullResIcon, mContext);
             widget.icon.data = Utilities.flattenBitmap(icon);
             widget.icon.dpi = dpi;
@@ -1023,7 +1026,6 @@
         Point spans = info.getMinSpans(mIdp, mContext);
         widget.minSpanX = spans.x;
         widget.minSpanY = spans.y;
-
         return widget;
     }
 
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index 772fbf3..069deb4 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -43,6 +43,8 @@
     public void onRequestPermissionsResult(int requestCode, String[] permissions,
             int[] grantResults);
     public void onWindowFocusChanged(boolean hasFocus);
+    public void onAttachedToWindow();
+    public void onDetachedFromWindow();
     public boolean onPrepareOptionsMenu(Menu menu);
     public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args);
     public void onHomeIntent();
@@ -69,18 +71,11 @@
     public void onInteractionBegin();
     public void onInteractionEnd();
 
-    /*
-     * Extension points for replacing the search experience
-     */
-    @Deprecated
-    public boolean forceDisableVoiceButtonProxy();
     public boolean providesSearch();
     public boolean startSearch(String initialQuery, boolean selectInitialQuery,
             Bundle appSearchData, Rect sourceBounds);
     @Deprecated
     public boolean startSearchFromAllApps(String query);
-    @Deprecated
-    public void startVoice();
     public boolean hasCustomContentToLeft();
     public void populateCustomContentContainer();
     public View getQsbBar();
@@ -95,8 +90,6 @@
     public View getIntroScreen();
     public boolean shouldMoveToDefaultScreenOnHomeIntent();
     public boolean hasSettings();
-    @Deprecated
-    public ComponentName getWallpaperPickerComponent();
     public boolean overrideWallpaperDimensions();
     public boolean isLauncherPreinstalled();
     public AllAppsSearchBarController getAllAppsSearchBarController();
@@ -106,24 +99,6 @@
     public int getSearchBarHeight();
 
     /**
-     * Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
-     * com.android.launcher3.Launcher.LauncherOverlayCallbacks)}.
-     *
-     * @return true if this launcher extension will provide an overlay
-     */
-    public boolean hasLauncherOverlay();
-
-    /**
-     * Handshake to establish an overlay relationship
-     *
-     * @param container Full screen overlay ViewGroup into which custom views can be placed.
-     * @param callbacks A set of callbacks provided by Launcher in relation to the overlay
-     * @return an interface used to make requests and notify the Launcher in relation to the overlay
-     */
-    public Launcher.LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
-            Launcher.LauncherOverlayCallbacks callbacks);
-
-    /**
      * Sets the callbacks to allow reacting the actions of search overlays of the launcher.
      *
      * @param callbacks A set of callbacks to the Launcher, is actually a LauncherSearchCallback,
diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java
index c08cd0b..6ce2293 100644
--- a/src/com/android/launcher3/LauncherFiles.java
+++ b/src/com/android/launcher3/LauncherFiles.java
@@ -34,7 +34,7 @@
             WALLPAPER_CROP_PREFERENCES_KEY + XML,
             WALLPAPER_IMAGES_DB,
             WIDGET_PREVIEWS_DB,
-            MANAGED_USER_PREFERENCES_KEY,
+            MANAGED_USER_PREFERENCES_KEY + XML,
             APP_ICONS_DB));
 
     // TODO: Delete these files on upgrade
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 774cca4..c8860e3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -17,7 +17,6 @@
 package com.android.launcher3;
 
 import android.app.SearchManager;
-import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -34,15 +33,12 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
-import android.os.DeadObjectException;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
-import android.os.TransactionTooLargeException;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
 import android.util.Log;
@@ -56,12 +52,15 @@
 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.model.MigrateFromRestoreTask;
+import com.android.launcher3.model.GridSizeMigrationTask;
 import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.CursorIconInfo;
+import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.LongArrayMap;
 import com.android.launcher3.util.ManagedProfileHeuristic;
+import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.StringFilter;
 import com.android.launcher3.util.Thunk;
 
 import java.lang.ref.WeakReference;
@@ -69,7 +68,6 @@
 import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -99,7 +97,6 @@
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
     private static final long INVALID_SCREEN_ID = -1L;
 
-    @Thunk final boolean mAppsCanBeOnRemoveableStorage;
     private final boolean mOldContentProviderExists;
 
     @Thunk final LauncherAppState mApp;
@@ -138,11 +135,9 @@
     @Thunk WeakReference<Callbacks> mCallbacks;
 
     // < only access in worker thread >
-    AllAppsList mBgAllAppsList;
+    private final AllAppsList mBgAllAppsList;
     // Entire list of widgets.
-    WidgetsModel mBgWidgetsModel;
-    // Keep a clone of widgets that can be accessed from non-worker thread.
-    WidgetsModel mFgWidgetsModel;
+    private final WidgetsModel mBgWidgetsModel;
 
     // The lock that must be acquired before referencing any static bg data structures.  Unlike
     // other locks, this one can generally be held long-term because we never expect any of these
@@ -169,12 +164,6 @@
     // sBgWorkspaceScreens is the ordered set of workspace screens.
     static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
 
-    // sBgWidgetProviders is the set of widget providers including custom internal widgets
-    public static HashMap<ComponentKey, LauncherAppWidgetProviderInfo> sBgWidgetProviders;
-
-    // sBgShortcutProviders is the set of custom shortcut providers
-    public static List<ResolveInfo> sBgShortcutProviders;
-
     // 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>>();
@@ -207,9 +196,12 @@
                 ArrayList<ShortcutInfo> removed, UserHandleCompat user);
         public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
         public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
-        public void bindComponentsRemoved(ArrayList<String> packageNames,
-                        ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
-        public void bindAllPackages(WidgetsModel model);
+        public void bindWorkspaceComponentsRemoved(
+                HashSet<String> packageNames, HashSet<ComponentName> components,
+                UserHandleCompat user);
+        public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
+        public void notifyWidgetProvidersChanged();
+        public void bindWidgetsModel(WidgetsModel model);
         public void bindSearchProviderChanged();
         public boolean isAllAppsButtonRank(int rank);
         public void onPageBoundSynchronously(int page);
@@ -223,7 +215,6 @@
     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
         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.
@@ -245,7 +236,6 @@
         mApp = app;
         mBgAllAppsList = new AllAppsList(iconCache, appFilter);
         mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter);
-        mFgWidgetsModel = mBgWidgetsModel.clone();
         mIconCache = iconCache;
 
         mLauncherApps = LauncherAppsCompat.getInstance(context);
@@ -1238,20 +1228,8 @@
     @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));
-        }
+        enqueuePackageUpdated(
+                new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, packageNames, user));
     }
 
     @Override
@@ -1264,6 +1242,20 @@
         }
     }
 
+    @Override
+    public void onPackagesSuspended(String[] packageNames, UserHandleCompat user) {
+        enqueuePackageUpdated(new PackageUpdatedTask(
+                PackageUpdatedTask.OP_SUSPEND, packageNames,
+                user));
+    }
+
+    @Override
+    public void onPackagesUnsuspended(String[] packageNames, UserHandleCompat user) {
+        enqueuePackageUpdated(new PackageUpdatedTask(
+                PackageUpdatedTask.OP_UNSUSPEND, packageNames,
+                user));
+    }
+
     /**
      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
      * ACTION_PACKAGE_CHANGED.
@@ -1285,6 +1277,14 @@
                 || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
             UserManagerCompat.getInstance(context).enableAndResetCache();
             forceReload();
+        } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action) ||
+                LauncherAppsCompat.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
+            UserHandleCompat user = UserHandleCompat.fromIntent(intent);
+            if (user != null) {
+                enqueuePackageUpdated(new PackageUpdatedTask(
+                        PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE,
+                        new String[0], user));
+            }
         }
     }
 
@@ -1736,23 +1736,10 @@
             int countX = profile.numColumns;
             int countY = profile.numRows;
 
-            if (MigrateFromRestoreTask.ENABLED && MigrateFromRestoreTask.shouldRunTask(mContext)) {
-                long migrationStartTime = System.currentTimeMillis();
-                Log.v(TAG, "Starting workspace migration after restore");
-                try {
-                    MigrateFromRestoreTask task = new MigrateFromRestoreTask(mContext);
-                    // Clear the flags before starting the task, so that we do not run the task
-                    // again, in case there was an uncaught error.
-                    MigrateFromRestoreTask.clearFlags(mContext);
-                    task.execute();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error during grid migration", e);
-
-                    // Clear workspace.
-                    mFlags = mFlags | LOADER_FLAG_CLEAR_WORKSPACE;
-                }
-                Log.v(TAG, "Workspace migration completed in "
-                        + (System.currentTimeMillis() - migrationStartTime));
+            if (GridSizeMigrationTask.ENABLED &&
+                    !GridSizeMigrationTask.migrateGridIfNeeded(mContext)) {
+                // Migration failed. Clear workspace.
+                mFlags = mFlags | LOADER_FLAG_CLEAR_WORKSPACE;
             }
 
             if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
@@ -1776,8 +1763,8 @@
                         .getInstance(mContext).updateAndGetActiveSessionCache();
                 sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
 
-                final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
-                final ArrayList<Long> restoredRows = new ArrayList<Long>();
+                final ArrayList<Long> itemsToRemove = new ArrayList<>();
+                final ArrayList<Long> restoredRows = new ArrayList<>();
                 final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
                 if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);
@@ -1786,6 +1773,7 @@
                 // Load workspace in reverse order to ensure that latest items are loaded first (and
                 // before any earlier duplicates)
                 final LongArrayMap<ItemInfo[][]> occupied = new LongArrayMap<>();
+                HashMap<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null;
 
                 try {
                     final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
@@ -1822,8 +1810,11 @@
                     final CursorIconInfo cursorIconInfo = new CursorIconInfo(c);
 
                     final LongSparseArray<UserHandleCompat> allUsers = new LongSparseArray<>();
+                    final LongSparseArray<Boolean> quietMode = new LongSparseArray<>();
                     for (UserHandleCompat user : mUserManager.getUserProfiles()) {
-                        allUsers.put(mUserManager.getSerialNumberForUser(user), user);
+                        long serialNo = mUserManager.getSerialNumberForUser(user);
+                        allUsers.put(serialNo, user);
+                        quietMode.put(serialNo, mUserManager.isQuietModeEnabled(user));
                     }
 
                     ShortcutInfo info;
@@ -1834,6 +1825,7 @@
                     long serialNumber;
                     Intent intent;
                     UserHandleCompat user;
+                    String targetPackage;
 
                     while (!mStopped && c.moveToNext()) {
                         try {
@@ -1852,6 +1844,7 @@
                                 int promiseType = c.getInt(restoredIndex);
                                 int disabledState = 0;
                                 boolean itemReplaced = false;
+                                targetPackage = null;
                                 if (user == null) {
                                     // User has been deleted remove the item.
                                     itemsToRemove.add(id);
@@ -1865,6 +1858,9 @@
                                                 cn.getPackageName(), user);
                                         boolean validComponent = validPkg &&
                                                 launcherApps.isActivityEnabledForProfile(cn, user);
+                                        if (validPkg) {
+                                            targetPackage = cn.getPackageName();
+                                        }
 
                                         if (validComponent) {
                                             if (restored) {
@@ -1872,6 +1868,9 @@
                                                 restoredRows.add(id);
                                                 restored = false;
                                             }
+                                            if (quietMode.get(serialNumber)) {
+                                                disabledState = ShortcutInfo.FLAG_DISABLED_QUIET_USER;
+                                            }
                                         } else if (validPkg) {
                                             intent = null;
                                             if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
@@ -1940,9 +1939,8 @@
                                                 itemsToRemove.add(id);
                                                 continue;
                                             }
-                                        } else if (launcherApps.isAppEnabled(
-                                                manager, cn.getPackageName(),
-                                                PackageManager.GET_UNINSTALLED_PACKAGES)) {
+                                        } else if (PackageManagerHelper.isAppOnSdcard(
+                                                manager, cn.getPackageName())) {
                                             // Package is present but not available.
                                             allowMissingTarget = true;
                                             disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
@@ -1985,7 +1983,7 @@
 
                                 if (itemReplaced) {
                                     if (user.equals(UserHandleCompat.myUserHandle())) {
-                                        info = getAppShortcutInfo(manager, intent, user, context, null,
+                                        info = getAppShortcutInfo(intent, user, context, null,
                                                 cursorIconInfo.iconIndex, titleIndex,
                                                 false, useLowResIcon);
                                     } else {
@@ -2008,12 +2006,17 @@
                                     }
                                 } else if (itemType ==
                                         LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                                    info = getAppShortcutInfo(manager, intent, user, context, c,
+                                    info = getAppShortcutInfo(intent, user, context, c,
                                             cursorIconInfo.iconIndex, titleIndex,
                                             allowMissingTarget, useLowResIcon);
                                 } else {
                                     info = getShortcutInfo(c, context, titleIndex, cursorIconInfo);
 
+                                    // Shortcuts are only available on the primary profile
+                                    if (PackageManagerHelper.isAppSuspended(manager, targetPackage)) {
+                                        disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+                                    }
+
                                     // App shortcuts that used to be automatically added to Launcher
                                     // didn't always have the correct intent flags set, so do that
                                     // here
@@ -2041,7 +2044,7 @@
                                     if (info.promisedIntent != null) {
                                         info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
                                     }
-                                    info.isDisabled = disabledState;
+                                    info.isDisabled |= disabledState;
                                     if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
                                         info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
                                     }
@@ -2144,10 +2147,14 @@
                                 final boolean wasProviderReady = (restoreStatus &
                                         LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
 
-                                final LauncherAppWidgetProviderInfo provider =
-                                        LauncherModel.getProviderInfo(context,
+                                if (widgetProvidersMap == null) {
+                                    widgetProvidersMap = AppWidgetManagerCompat
+                                            .getInstance(mContext).getAllProvidersMap();
+                                }
+                                final AppWidgetProviderInfo provider = widgetProvidersMap.get(
+                                        new ComponentKey(
                                                 ComponentName.unflattenFromString(savedProvider),
-                                                user);
+                                                user));
 
                                 final boolean isProviderReady = isValidProvider(provider);
                                 if (!isSafeMode && !customWidget &&
@@ -2766,7 +2773,6 @@
                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                     if (callbacks != null) {
                         callbacks.bindAllApplications(list);
-                        callbacks.bindAllPackages(mFgWidgetsModel);
                     }
                     if (DEBUG_LOADERS) {
                         Log.d(TAG, "bound all " + list.size() + " apps from cache in "
@@ -2810,12 +2816,12 @@
                 if (apps == null || apps.isEmpty()) {
                     return;
                 }
-
+                boolean quietMode = mUserManager.isQuietModeEnabled(user);
                 // 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));
+                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, quietMode));
                 }
 
                 final ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
@@ -2858,7 +2864,7 @@
                         callbacks.bindAllApplications(added);
                         if (DEBUG_LOADERS) {
                             Log.d(TAG, "bound " + added.size() + " apps in "
-                                + (SystemClock.uptimeMillis() - bindTime) + "ms");
+                                    + (SystemClock.uptimeMillis() - bindTime) + "ms");
                         }
                     } else {
                         Log.i(TAG, "not binding apps: no Launcher activity");
@@ -2867,8 +2873,6 @@
             });
             // Cleanup any data stored for a deleted user.
             ManagedProfileHeuristic.processAllUsers(profiles, mContext);
-
-            loadAndBindWidgetsAndShortcuts(tryGetCallbacks(oldCallbacks), true /* refresh */);
             if (DEBUG_LOADERS) {
                 Log.d(TAG, "Icons processed in "
                         + (SystemClock.uptimeMillis() - loadTime) + "ms");
@@ -2935,9 +2939,6 @@
                 }
             });
         }
-
-        // Reload widget list. No need to refresh, as we only want to update the icons and labels.
-        loadAndBindWidgetsAndShortcuts(callbacks, false);
     }
 
     void enqueuePackageUpdated(PackageUpdatedTask task) {
@@ -2960,10 +2961,7 @@
                     packagesUnavailable.clear();
                     for (String pkg : entry.getValue()) {
                         if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
-                            boolean packageOnSdcard = launcherApps.isAppEnabled(
-                                    manager, pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
-                            if (packageOnSdcard) {
-                                Launcher.addDumpLog(TAG, "Package found on sd-card: " + pkg, true);
+                            if (PackageManagerHelper.isAppOnSdcard(manager, pkg)) {
                                 packagesUnavailable.add(pkg);
                             } else {
                                 Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
@@ -2995,7 +2993,9 @@
         public static final int OP_UPDATE = 2;
         public static final int OP_REMOVE = 3; // uninstlled
         public static final int OP_UNAVAILABLE = 4; // external media unmounted
-
+        public static final int OP_SUSPEND = 5; // package suspended
+        public static final int OP_UNSUSPEND = 6; // package unsuspended
+        public static final int OP_USER_AVAILABILITY_CHANGE = 7; // user available/unavailable
 
         public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
             mOp = op;
@@ -3012,6 +3012,8 @@
 
             final String[] packages = mPackages;
             final int N = packages.length;
+            FlagOp flagOp = FlagOp.NO_OP;
+            StringFilter pkgFilter = StringFilter.of(new HashSet<>(Arrays.asList(packages)));
             switch (mOp) {
                 case OP_ADD: {
                     for (int i=0; i<N; i++) {
@@ -3033,6 +3035,8 @@
                         mBgAllAppsList.updatePackage(context, packages[i], mUser);
                         mApp.getWidgetCache().removePackage(packages[i], mUser);
                     }
+                    // Since package was just updated, the target must be available now.
+                    flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
                     break;
                 case OP_REMOVE: {
                     ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
@@ -3051,6 +3055,23 @@
                         mBgAllAppsList.removePackage(packages[i], mUser);
                         mApp.getWidgetCache().removePackage(packages[i], mUser);
                     }
+                    flagOp = FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
+                    break;
+                case OP_SUSPEND:
+                case OP_UNSUSPEND:
+                    flagOp = mOp == OP_SUSPEND ?
+                            FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED) :
+                                    FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED);
+                    if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.(un)suspend " + N);
+                    mBgAllAppsList.updatePackageFlags(pkgFilter, mUser, flagOp);
+                    break;
+                case OP_USER_AVAILABILITY_CHANGE:
+                    flagOp = UserManagerCompat.getInstance(context).isQuietModeEnabled(mUser)
+                            ? FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_QUIET_USER)
+                            : FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_QUIET_USER);
+                    // We want to update all packages for this user.
+                    pkgFilter = StringFilter.matchesAll();
+                    mBgAllAppsList.updatePackageFlags(pkgFilter, mUser, flagOp);
                     break;
             }
 
@@ -3059,11 +3080,11 @@
             final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();
 
             if (mBgAllAppsList.added.size() > 0) {
-                added = new ArrayList<AppInfo>(mBgAllAppsList.added);
+                added = new ArrayList<>(mBgAllAppsList.added);
                 mBgAllAppsList.added.clear();
             }
             if (mBgAllAppsList.modified.size() > 0) {
-                modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);
+                modified = new ArrayList<>(mBgAllAppsList.modified);
                 mBgAllAppsList.modified.clear();
             }
             if (mBgAllAppsList.removed.size() > 0) {
@@ -3071,14 +3092,7 @@
                 mBgAllAppsList.removed.clear();
             }
 
-            final Callbacks callbacks = getCallback();
-            if (callbacks == null) {
-                Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");
-                return;
-            }
-
-            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
-                    new HashMap<ComponentName, AppInfo>();
+            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps = new HashMap<>();
 
             if (added != null) {
                 addAppsToAllApps(context, added);
@@ -3088,6 +3102,7 @@
             }
 
             if (modified != null) {
+                final Callbacks callbacks = getCallback();
                 final ArrayList<AppInfo> modifiedFinal = modified;
                 for (AppInfo ai : modified) {
                     addedOrUpdatedApps.put(ai.componentName, ai);
@@ -3104,12 +3119,11 @@
             }
 
             // Update shortcut infos
-            if (mOp == OP_ADD || mOp == OP_UPDATE) {
+            if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
                 final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
                 final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
                 final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
 
-                HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
                 synchronized (sBgLock) {
                     for (ItemInfo info : sBgItemsIdMap) {
                         if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
@@ -3119,7 +3133,7 @@
 
                             // Update shortcuts which use iconResource.
                             if ((si.iconResource != null)
-                                    && packageSet.contains(si.iconResource.packageName)) {
+                                    && pkgFilter.matches(si.iconResource.packageName)) {
                                 Bitmap icon = Utilities.createIconBitmap(
                                         si.iconResource.packageName,
                                         si.iconResource.resourceName, context);
@@ -3131,7 +3145,7 @@
                             }
 
                             ComponentName cn = si.getTargetComponent();
-                            if (cn != null && packageSet.contains(cn.getPackageName())) {
+                            if (cn != null && pkgFilter.matches(cn.getPackageName())) {
                                 AppInfo appInfo = addedOrUpdatedApps.get(cn);
 
                                 if (si.isPromise()) {
@@ -3179,9 +3193,9 @@
                                     infoUpdated = true;
                                 }
 
-                                if ((si.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
-                                    // Since package was just updated, the target must be available now.
-                                    si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
+                                int oldDisabledFlags = si.isDisabled;
+                                si.isDisabled = flagOp.apply(si.isDisabled);
+                                if (si.isDisabled != oldDisabledFlags) {
                                     shortcutUpdated = true;
                                 }
                             }
@@ -3192,11 +3206,11 @@
                             if (infoUpdated) {
                                 updateItemInDatabase(context, si);
                             }
-                        } else if (info instanceof LauncherAppWidgetInfo) {
+                        } else if (info instanceof LauncherAppWidgetInfo && mOp == OP_ADD) {
                             LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
                             if (mUser.equals(widgetInfo.user)
                                     && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
-                                    && packageSet.contains(widgetInfo.providerName.getPackageName())) {
+                                    && pkgFilter.matches(widgetInfo.providerName.getPackageName())) {
                                 widgetInfo.restoreStatus &=
                                         ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY &
                                         ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
@@ -3214,6 +3228,7 @@
                 }
 
                 if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
+                    final Callbacks callbacks = getCallback();
                     mHandler.post(new Runnable() {
 
                         public void run() {
@@ -3229,6 +3244,7 @@
                     }
                 }
                 if (!widgets.isEmpty()) {
+                    final Callbacks callbacks = getCallback();
                     mHandler.post(new Runnable() {
                         public void run() {
                             Callbacks cb = getCallback();
@@ -3240,222 +3256,109 @@
                 }
             }
 
-            final ArrayList<String> removedPackageNames =
-                    new ArrayList<String>();
-            if (mOp == OP_REMOVE || mOp == OP_UNAVAILABLE) {
+            final HashSet<String> removedPackages = new HashSet<>();
+            final HashSet<ComponentName> removedComponents = new HashSet<>();
+            if (mOp == OP_REMOVE) {
                 // Mark all packages in the broadcast to be removed
-                removedPackageNames.addAll(Arrays.asList(packages));
+                Collections.addAll(removedPackages, packages);
+
+                // No need to update the removedComponents as
+                // removedPackages is a super-set of removedComponents
             } else if (mOp == OP_UPDATE) {
                 // Mark disabled packages in the broadcast to be removed
                 for (int i=0; i<N; i++) {
                     if (isPackageDisabled(context, packages[i], mUser)) {
-                        removedPackageNames.add(packages[i]);
+                        removedPackages.add(packages[i]);
                     }
                 }
+
+                // Update removedComponents as some components can get removed during package update
+                for (AppInfo info : removedApps) {
+                    removedComponents.add(info.componentName);
+                }
             }
 
-            if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {
-                final int removeReason;
-                if (mOp == OP_UNAVAILABLE) {
-                    removeReason = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
-                } else {
-                    // Remove all the components associated with this package
-                    for (String pn : removedPackageNames) {
-                        deletePackageFromDatabase(context, pn, mUser);
-                    }
-                    // Remove all the specific components
-                    for (AppInfo a : removedApps) {
-                        ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);
-                        deleteItemsFromDatabase(context, infos);
-                    }
-                    removeReason = 0;
+            if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
+                for (String pn : removedPackages) {
+                    deletePackageFromDatabase(context, pn, mUser);
+                }
+                for (ComponentName cn : removedComponents) {
+                    deleteItemsFromDatabase(context, getItemInfoForComponentName(cn, mUser));
                 }
 
                 // Remove any queued items from the install queue
-                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackageNames, mUser);
+                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
+
                 // Call the components-removed callback
+                final Callbacks callbacks = getCallback();
                 mHandler.post(new Runnable() {
                     public void run() {
                         Callbacks cb = getCallback();
                         if (callbacks == cb && cb != null) {
-                            callbacks.bindComponentsRemoved(
-                                    removedPackageNames, removedApps, mUser, removeReason);
+                            callbacks.bindWorkspaceComponentsRemoved(
+                                    removedPackages, removedComponents, mUser);
                         }
                     }
                 });
             }
 
-            // Update widgets
-            if (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE) {
-                // Always refresh for a package event on secondary user
-                boolean needToRefresh = !mUser.equals(UserHandleCompat.myUserHandle());
-
-                // Refresh widget list, if the package already had a widget.
-                synchronized (sBgLock) {
-                    if (sBgWidgetProviders != null) {
-                        HashSet<String> pkgSet = new HashSet<>();
-                        Collections.addAll(pkgSet, mPackages);
-
-                        for (ComponentKey key : sBgWidgetProviders.keySet()) {
-                            needToRefresh |= key.user.equals(mUser) &&
-                                    pkgSet.contains(key.componentName.getPackageName());
+            if (!removedApps.isEmpty()) {
+                // Remove corresponding apps from All-Apps
+                final Callbacks callbacks = getCallback();
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = getCallback();
+                        if (callbacks == cb && cb != null) {
+                            callbacks.bindAppInfosRemoved(removedApps);
                         }
                     }
-                }
+                });
+            }
 
-                if (!needToRefresh && mOp != OP_REMOVE) {
-                    // Refresh widget list, if there is any newly added widget
-                    PackageManager pm = context.getPackageManager();
-                    for (String pkg : mPackages) {
-                        try {
-                            List<ResolveInfo> widgets = pm.queryBroadcastReceivers(
-                                    new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
-                                            .setPackage(pkg), 0);
-                            needToRefresh |= widgets != null && !widgets.isEmpty();
-                        } catch (RuntimeException e) {
-                            if (LauncherAppState.isDogfoodBuild()) {
-                                throw e;
-                            }
-                            // Ignore the crash. We can live with a state widget list.
-                            Log.e(TAG, "PM call failed for " + pkg, e);
+            // Notify launcher of widget update. From marshmallow onwards we use AppWidgetHost to
+            // get widget update signals.
+            if (!Utilities.ATLEAST_MARSHMALLOW &&
+                    (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) {
+                final Callbacks callbacks = getCallback();
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = getCallback();
+                        if (callbacks == cb && cb != null) {
+                            callbacks.notifyWidgetProvidersChanged();
                         }
                     }
-                }
-
-                loadAndBindWidgetsAndShortcuts(callbacks, needToRefresh);
-            }
-
-            // Write all the logs to disk
-            mHandler.post(new Runnable() {
-                public void run() {
-                    Callbacks cb = getCallback();
-                    if (callbacks == cb && cb != null) {
-                        callbacks.dumpLogsToLocalData();
-                    }
-                }
-            });
-        }
-    }
-
-    public static List<LauncherAppWidgetProviderInfo> getWidgetProviders(Context context,
-            boolean refresh) {
-        ArrayList<LauncherAppWidgetProviderInfo> results =
-                new ArrayList<LauncherAppWidgetProviderInfo>();
-        try {
-            synchronized (sBgLock) {
-                if (sBgWidgetProviders == null || refresh) {
-                    HashMap<ComponentKey, LauncherAppWidgetProviderInfo> tmpWidgetProviders
-                            = new HashMap<>();
-                    AppWidgetManagerCompat wm = AppWidgetManagerCompat.getInstance(context);
-                    LauncherAppWidgetProviderInfo info;
-
-                    List<AppWidgetProviderInfo> widgets = wm.getAllProviders();
-                    for (AppWidgetProviderInfo pInfo : widgets) {
-                        info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, pInfo);
-                        UserHandleCompat user = wm.getUser(info);
-                        tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
-                    }
-
-                    Collection<CustomAppWidget> customWidgets = Launcher.getCustomAppWidgets().values();
-                    for (CustomAppWidget widget : customWidgets) {
-                        info = new LauncherAppWidgetProviderInfo(context, widget);
-                        UserHandleCompat user = wm.getUser(info);
-                        tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
-                    }
-                    // Replace the global list at the very end, so that if there is an exception,
-                    // previously loaded provider list is used.
-                    sBgWidgetProviders = tmpWidgetProviders;
-                }
-                results.addAll(sBgWidgetProviders.values());
-                return results;
-            }
-        } catch (Exception e) {
-            if (!LauncherAppState.isDogfoodBuild() &&
-                    (e.getCause() instanceof TransactionTooLargeException ||
-                    e.getCause() instanceof DeadObjectException)) {
-                // the returned value may be incomplete and will not be refreshed until the next
-                // time Launcher starts.
-                // TODO: after figuring out a repro step, introduce a dirty bit to check when
-                // onResume is called to refresh the widget provider list.
-                synchronized (sBgLock) {
-                    if (sBgWidgetProviders != null) {
-                        results.addAll(sBgWidgetProviders.values());
-                    }
-                    return results;
-                }
-            } else {
-                throw e;
+                });
             }
         }
     }
 
-    public static LauncherAppWidgetProviderInfo getProviderInfo(Context ctx, ComponentName name,
-            UserHandleCompat user) {
-        synchronized (sBgLock) {
-            if (sBgWidgetProviders == null) {
-                getWidgetProviders(ctx, false /* refresh */);
-            }
-            return sBgWidgetProviders.get(new ComponentKey(name, user));
-        }
-    }
-
-    public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {
-
-        runOnWorkerThread(new Runnable() {
+    private void bindWidgetsModel(final Callbacks callbacks, final WidgetsModel model) {
+        mHandler.post(new Runnable() {
             @Override
             public void run() {
-                updateWidgetsModel(refresh);
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        Callbacks cb = getCallback();
-                        if (callbacks == cb && cb != null) {
-                            callbacks.bindAllPackages(mFgWidgetsModel);
-                        }
-                    }
-                });
-                // update the Widget entries inside DB on the worker thread.
-                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
-                        mFgWidgetsModel.getRawList());
+                Callbacks cb = getCallback();
+                if (callbacks == cb && cb != null) {
+                    callbacks.bindWidgetsModel(model);
+                }
             }
         });
     }
 
-    /**
-     * Returns a list of ResolveInfos/AppWidgetInfos.
-     *
-     * @see #loadAndBindWidgetsAndShortcuts
-     */
-    @Thunk void updateWidgetsModel(boolean refresh) {
-        Utilities.assertWorkerThread();
-        PackageManager packageManager = mApp.getContext().getPackageManager();
-        final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
-        widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
-
-        // Update shortcut providers
-        synchronized (sBgLock) {
-            try {
-                Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
-                List<ResolveInfo> providers = packageManager.queryIntentActivities(shortcutsIntent, 0);
-                sBgShortcutProviders = providers;
-            } catch (RuntimeException e) {
-                if (!LauncherAppState.isDogfoodBuild() &&
-                        (e.getCause() instanceof TransactionTooLargeException ||
-                                e.getCause() instanceof DeadObjectException)) {
-                    /**
-                     * Ignore exception and use the cached list if available.
-                     * Refer to {@link #getWidgetProviders(Context, boolean}} for more info.
-                     */
-                } else {
-                    throw e;
+    public void refreshAndBindWidgetsAndShortcuts(
+            final Callbacks callbacks, final boolean bindFirst) {
+        runOnWorkerThread(new Runnable() {
+            @Override
+            public void run() {
+                if (bindFirst && !mBgWidgetsModel.isEmpty()) {
+                    bindWidgetsModel(callbacks, mBgWidgetsModel.clone());
                 }
+                final WidgetsModel model = mBgWidgetsModel.updateAndClone(mApp.getContext());
+                bindWidgetsModel(callbacks, model);
+                // update the Widget entries inside DB on the worker thread.
+                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
+                        model.getRawList());
             }
-            if (sBgShortcutProviders != null) {
-                widgetsAndShortcuts.addAll(sBgShortcutProviders);
-            }
-        }
-        mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
-        mFgWidgetsModel = mBgWidgetsModel.clone();
+        });
     }
 
     @Thunk static boolean isPackageDisabled(Context context, String packageName,
@@ -3545,7 +3448,7 @@
      *
      * If c is not null, then it will be used to fill in missing data like the title and icon.
      */
-    public ShortcutInfo getAppShortcutInfo(PackageManager manager, Intent intent,
+    public ShortcutInfo getAppShortcutInfo(Intent intent,
             UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
             boolean allowMissingTarget, boolean useLowResIcon) {
         if (user == null) {
@@ -3575,6 +3478,10 @@
             info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
         }
 
+        if (lai != null && PackageManagerHelper.isAppSuspended(lai.getApplicationInfo())) {
+            info.isDisabled = ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+        }
+
         // from the db
         if (TextUtils.isEmpty(info.title) && c != null) {
             info.title =  Utilities.trim(c.getString(titleIndex));
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 4760930..7c4b78d 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -78,7 +78,7 @@
     private static final String RESTRICTION_PACKAGE_NAME = "workspace.configuration.package.name";
 
     @Thunk LauncherProviderChangeListener mListener;
-    @Thunk DatabaseHelper mOpenHelper;
+    protected DatabaseHelper mOpenHelper;
 
     @Override
     public boolean onCreate() {
@@ -113,6 +113,15 @@
         }
     }
 
+    /**
+     * Overridden in tests
+     */
+    protected synchronized void createDbIfNotExists() {
+        if (mOpenHelper == null) {
+            mOpenHelper = new DatabaseHelper(getContext());
+        }
+    }
+
     @Override
     public Cursor query(Uri uri, String[] projection, String selection,
             String[] selectionArgs, String sortOrder) {
@@ -259,9 +268,14 @@
         switch (method) {
             case LauncherSettings.Settings.METHOD_GET_BOOLEAN: {
                 Bundle result = new Bundle();
-                result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
-                        Utilities.getPrefs(getContext()).getBoolean(arg, extras.getBoolean(
-                                LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
+                if (Utilities.ALLOW_ROTATION_PREFERENCE_KEY.equals(arg)) {
+                    result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+                            Utilities.isAllowRotationPrefEnabled(getContext()));
+                } else {
+                    result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+                            Utilities.getPrefs(getContext()).getBoolean(arg, extras.getBoolean(
+                                    LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
+                }
                 return result;
             }
             case LauncherSettings.Settings.METHOD_SET_BOOLEAN: {
@@ -317,7 +331,10 @@
         return folderIds;
     }
 
-    private void notifyListeners() {
+    /**
+     * Overridden in tests
+     */
+    protected void notifyListeners() {
         // always notify the backup agent
         LauncherBackupAgentHelper.dataChanged(getContext());
         if (mListener != null) {
@@ -459,7 +476,10 @@
         mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
     }
 
-    private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
+    /**
+     * The class is subclassed in tests to create an in-memory db.
+     */
+    protected static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
         private final Context mContext;
         @Thunk final AppWidgetHost mAppWidgetHost;
         private long mMaxItemId = -1;
@@ -494,6 +514,18 @@
             }
         }
 
+        /**
+         * Constructor used only in tests.
+         */
+        public DatabaseHelper(Context context, String tableName) {
+            super(context, tableName, null, DATABASE_VERSION);
+            mContext = context;
+
+            mAppWidgetHost = null;
+            mMaxItemId = initializeMaxItemId(getWritableDatabase());
+            mMaxScreenId = initializeMaxScreenId(getWritableDatabase());
+        }
+
         private boolean tableExists(String tableName) {
             Cursor c = getReadableDatabase().query(
                     true, "sqlite_master", new String[] {"tbl_name"},
@@ -544,18 +576,28 @@
 
             // Fresh and clean launcher DB.
             mMaxItemId = initializeMaxItemId(db);
-            setFlagEmptyDbCreated();
+            onEmptyDbCreated();
+        }
+
+        /**
+         * Overriden in tests.
+         */
+        protected void onEmptyDbCreated() {
+            // Set the flag for empty DB
+            Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
 
             // When a new DB is created, remove all previously stored managed profile information.
-            ManagedProfileHeuristic.processAllUsers(Collections.<UserHandleCompat>emptyList(), mContext);
+            ManagedProfileHeuristic.processAllUsers(Collections.<UserHandleCompat>emptyList(),
+                    mContext);
+        }
+
+        protected long getDefaultUserSerial() {
+            return UserManagerCompat.getInstance(mContext).getSerialNumberForUser(
+                    UserHandleCompat.myUserHandle());
         }
 
         private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
-            UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
-            long userSerialNumber = userManager.getSerialNumberForUser(
-                    UserHandleCompat.myUserHandle());
             String ifNotExists = optional ? " IF NOT EXISTS " : "";
-
             db.execSQL("CREATE TABLE " + ifNotExists + TABLE_FAVORITES + " (" +
                     "_id INTEGER PRIMARY KEY," +
                     "title TEXT," +
@@ -578,7 +620,7 @@
                     "appWidgetProvider TEXT," +
                     "modified INTEGER NOT NULL DEFAULT 0," +
                     "restored INTEGER NOT NULL DEFAULT 0," +
-                    "profileId INTEGER DEFAULT " + userSerialNumber + "," +
+                    "profileId INTEGER DEFAULT " + getDefaultUserSerial() + "," +
                     "rank INTEGER NOT NULL DEFAULT 0," +
                     "options INTEGER NOT NULL DEFAULT 0" +
                     ");");
@@ -628,10 +670,6 @@
             Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
         }
 
-        private void setFlagEmptyDbCreated() {
-            Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
-        }
-
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             if (LOGD) Log.d(TAG, "onUpgrade triggered: " + oldVersion);
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 01d670d..55e6395 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -113,7 +113,7 @@
         /**
          * The content:// style URL for this table
          */
-        static final Uri CONTENT_URI = Uri.parse("content://" +
+        public static final Uri CONTENT_URI = Uri.parse("content://" +
                 ProviderConfig.AUTHORITY + "/" + TABLE_NAME);
 
         /**
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 30cae31..b95e2b0 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -702,7 +702,7 @@
     private void startWorkspaceSearchBarAnimation(
             final Workspace.State toWorkspaceState, int duration, AnimatorSet animation) {
         final SearchDropTargetBar.State toSearchBarState =
-                toWorkspaceState.getSearchDropTargetBarState();
+                toWorkspaceState.searchDropTargetBarState;
         mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration, animation);
     }
 
diff --git a/src/com/android/launcher3/LogAccelerateInterpolator.java b/src/com/android/launcher3/LogAccelerateInterpolator.java
index c3bbfa5..519d391 100644
--- a/src/com/android/launcher3/LogAccelerateInterpolator.java
+++ b/src/com/android/launcher3/LogAccelerateInterpolator.java
@@ -20,6 +20,8 @@
 
     @Override
     public float getInterpolation(float t) {
-        return 1 - computeLog(1 - t, mBase, mDrift) * mLogScale;
+        // Due to rounding issues, the interpolation doesn't quite reach 1 even though it should.
+        // To account for this, we short-circuit to return 1 if the input is 1.
+        return Float.compare(t, 1f) == 0 ? 1f : 1 - computeLog(1 - t, mBase, mDrift) * mLogScale;
     }
 }
diff --git a/src/com/android/launcher3/LogDecelerateInterpolator.java b/src/com/android/launcher3/LogDecelerateInterpolator.java
index 4c5f6f0..7d95282 100644
--- a/src/com/android/launcher3/LogDecelerateInterpolator.java
+++ b/src/com/android/launcher3/LogDecelerateInterpolator.java
@@ -21,6 +21,8 @@
 
     @Override
     public float getInterpolation(float t) {
-        return computeLog(t, mBase, mDrift) * mLogScale;
+        // Due to rounding issues, the interpolation doesn't quite reach 1 even though it should.
+        // To account for this, we short-circuit to return 1 if the input is 1.
+        return Float.compare(t, 1f) == 0 ? 1f : computeLog(t, mBase, mDrift) * mLogScale;
     }
 }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 2dcff35..b0e46f9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -156,7 +156,7 @@
 
     protected boolean mIsPageMoving = false;
 
-    private boolean mWasInOverscroll = false;
+    protected boolean mWasInOverscroll = false;
 
     // Page Indicator
     @Thunk int mPageIndicatorViewId;
@@ -551,9 +551,13 @@
         super.setOnLongClickListener(l);
     }
 
+    protected int getUnboundedScrollX() {
+        return getScrollX();
+    }
+
     @Override
     public void scrollBy(int x, int y) {
-        scrollTo(getScrollX() + x, getScrollY() + y);
+        scrollTo(getUnboundedScrollX() + x, getScrollY() + y);
     }
 
     @Override
@@ -1051,16 +1055,16 @@
     }
 
     protected void getVisiblePages(int[] range) {
-        final int pageCount = getChildCount();
+        final int count = getChildCount();
         range[0] = -1;
         range[1] = -1;
 
-        if (pageCount > 0) {
+        if (count > 0) {
             final int visibleLeft = -getLeft();
             final int visibleRight = visibleLeft + getViewportWidth();
+            final Matrix pageShiftMatrix = getPageShiftMatrix();
             int curScreen = 0;
 
-            int count = getChildCount();
             for (int i = 0; i < count; i++) {
                 View currPage = getPageAt(i);
 
@@ -1069,7 +1073,7 @@
                 sTmpRectF.right = currPage.getMeasuredWidth();
                 currPage.getMatrix().mapRect(sTmpRectF);
                 sTmpRectF.offset(currPage.getLeft() - getScrollX(), 0);
-                getMatrix().mapRect(sTmpRectF);
+                pageShiftMatrix.mapRect(sTmpRectF);
 
                 if (sTmpRectF.left > visibleRight || sTmpRectF.right < visibleLeft) {
                     if (range[0] == -1) {
@@ -1092,6 +1096,10 @@
         }
     }
 
+    protected Matrix getPageShiftMatrix() {
+        return getMatrix();
+    }
+
     protected boolean shouldDrawChild(View child) {
         return child.getVisibility() == VISIBLE;
     }
@@ -2008,7 +2016,7 @@
         int halfScreenSize = getViewportWidth() / 2;
 
         final int newX = getScrollForPage(whichPage);
-        int delta = newX - getScrollX();
+        int delta = newX - getUnboundedScrollX();
         int duration = 0;
 
         if (Math.abs(velocity) < mMinFlingVelocity) {
@@ -2058,7 +2066,7 @@
         whichPage = validateNewPage(whichPage);
 
         int newX = getScrollForPage(whichPage);
-        final int delta = newX - getScrollX();
+        final int delta = newX - getUnboundedScrollX();
         snapToPage(whichPage, delta, duration, immediate, interpolator);
     }
 
@@ -2090,7 +2098,7 @@
             mScroller.setInterpolator(mDefaultInterpolator);
         }
 
-        mScroller.startScroll(getScrollX(), 0, delta, 0, duration);
+        mScroller.startScroll(getUnboundedScrollX(), 0, delta, 0, duration);
 
         updatePageIndicator();
 
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 6bdcb4b..60e080e 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -113,6 +113,16 @@
     public static final int FLAG_DISABLED_NOT_AVAILABLE = 2;
 
     /**
+     * Indicates that the icon is disabled as the app is suspended
+     */
+    public static final int FLAG_DISABLED_SUSPENDED = 4;
+
+    /**
+     * Indicates that the icon is disabled as the user is in quiet mode.
+     */
+    public static final int FLAG_DISABLED_QUIET_USER = 8;
+
+    /**
      * Could be disabled, if the the app is installed but unavailable (eg. in safe mode or when
      * sd-card is not available).
      */
@@ -178,6 +188,7 @@
         intent = new Intent(info.intent);
         customIcon = false;
         flags = info.flags;
+        isDisabled = info.isDisabled;
     }
 
     public void setIcon(Bitmap b) {
@@ -288,5 +299,10 @@
         shortcut.flags = AppInfo.initFlags(info);
         return shortcut;
     }
+
+    @Override
+    public boolean isDisabled() {
+        return isDisabled != 0;
+    }
 }
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 87c9262..78ba22e 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -19,6 +19,7 @@
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.SearchManager;
+import android.app.WallpaperManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
@@ -45,6 +46,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.Process;
@@ -117,6 +119,18 @@
     public static final boolean ATLEAST_JB_MR2 =
             Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
 
+    public static boolean isNycOrAbove() {
+        // TODO: Replace using reflection with looking at the API version once
+        // Build.VERSION.SDK_INT gets bumped to 24. b/22942492.
+        try {
+            View.class.getDeclaredField("DRAG_FLAG_OPAQUE");
+            // View.DRAG_FLAG_OPAQUE doesn't exist in M-release, so it's an indication of N+.
+            return true;
+        } catch (NoSuchFieldException e) {
+            return false;
+        }
+    }
+
     // These values are same as that in {@link AsyncTask}.
     private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
     private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
@@ -129,27 +143,30 @@
             CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
             TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
 
-    // To turn on these properties, type
-    // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
-    private static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
-    private static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
-
     public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
 
     public static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);
     }
 
-    public static boolean isAllowRotationPrefEnabled(Context context, boolean multiProcess) {
-        SharedPreferences sharedPrefs = context.getSharedPreferences(
-                LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE | (multiProcess ?
-                        Context.MODE_MULTI_PROCESS : 0));
-        boolean allowRotationPref = sharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false);
-        return sForceEnableRotation || allowRotationPref;
-    }
-
-    public static boolean isRotationAllowedForDevice(Context context) {
-        return sForceEnableRotation || context.getResources().getBoolean(R.bool.allow_rotation);
+    public static boolean isAllowRotationPrefEnabled(Context context) {
+        boolean allowRotationPref = false;
+        if (isNycOrAbove()) {
+            // If the device was scaled, used the original dimensions to determine if rotation
+            // is allowed of not.
+            try {
+                // TODO: Use the actual field when the API is finalized.
+                int originalDensity =
+                        DisplayMetrics.class.getField("DENSITY_DEVICE_STABLE").getInt(null);
+                Resources res = context.getResources();
+                int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp
+                        * res.getDisplayMetrics().densityDpi / originalDensity;
+                allowRotationPref = originalSmallestWidth >= 600;
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+        return getPrefs(context).getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, allowRotationPref);
     }
 
     public static Bitmap createIconBitmap(Cursor c, int iconIndex, Context context) {
@@ -806,6 +823,17 @@
         return ATLEAST_LOLLIPOP && powerManager.isPowerSaveMode();
     }
 
+    public static boolean isWallapaperAllowed(Context context) {
+        if (isNycOrAbove()) {
+            try {
+                WallpaperManager wm = context.getSystemService(WallpaperManager.class);
+                return (Boolean) wm.getClass().getDeclaredMethod("isSetWallpaperAllowed")
+                        .invoke(wm);
+            } catch (Exception e) { }
+        }
+        return true;
+    }
+
     /**
      * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
      * This allows the badging to be done based on the action bitmap size rather than
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7b873d4..4eb4d45 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -55,6 +55,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.TextView;
@@ -68,6 +69,7 @@
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
 import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.util.LongArrayMap;
 import com.android.launcher3.util.Thunk;
@@ -171,6 +173,7 @@
     @Thunk float[] mDragViewVisualCenter = new float[2];
     private float[] mTempCellLayoutCenterCoordinates = new float[2];
     private Matrix mTempInverseMatrix = new Matrix();
+    private Matrix mTempMatrix = new Matrix();
 
     private SpringLoadedDragController mSpringLoadedDragController;
     private float mSpringLoadedShrinkFactor;
@@ -180,22 +183,20 @@
     // in all apps or customize mode)
 
     enum State {
-        NORMAL          (SearchDropTargetBar.State.SEARCH_BAR),
-        NORMAL_HIDDEN   (SearchDropTargetBar.State.INVISIBLE_TRANSLATED),
-        SPRING_LOADED   (SearchDropTargetBar.State.DROP_TARGET),
-        OVERVIEW        (SearchDropTargetBar.State.INVISIBLE),
-        OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE);
+        NORMAL          (SearchDropTargetBar.State.SEARCH_BAR, false),
+        NORMAL_HIDDEN   (SearchDropTargetBar.State.INVISIBLE_TRANSLATED, false),
+        SPRING_LOADED   (SearchDropTargetBar.State.DROP_TARGET, false),
+        OVERVIEW        (SearchDropTargetBar.State.INVISIBLE, true),
+        OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE, true);
 
-        private final SearchDropTargetBar.State mBarState;
+        public final SearchDropTargetBar.State searchDropTargetBarState;
+        public final boolean shouldUpdateWidget;
 
-        State(SearchDropTargetBar.State searchBarState) {
-            mBarState = searchBarState;
+        State(SearchDropTargetBar.State searchBarState, boolean shouldUpdateWidget) {
+            searchDropTargetBarState = searchBarState;
+            this.shouldUpdateWidget = shouldUpdateWidget;
         }
-
-        public SearchDropTargetBar.State getSearchDropTargetBarState() {
-            return mBarState;
-        }
-    };
+    }
 
     private State mState = State.NORMAL;
     private boolean mIsSwitchingState = false;
@@ -276,8 +277,11 @@
     LauncherOverlay mLauncherOverlay;
     boolean mScrollInteractionBegan;
     boolean mStartedSendingScrollEvents;
-    boolean mShouldSendPageSettled;
-    int mLastOverlaySroll = 0;
+    float mLastOverlaySroll = 0;
+    // Total over scrollX in the overlay direction.
+    private int mUnboundedScrollX;
+    // Total over scrollX in the overlay direction.
+    private float mOverlayTranslation;
 
     // Handles workspace state transitions
     private WorkspaceStateTransitionAnimation mStateTransitionAnimation;
@@ -1233,11 +1237,6 @@
             stripEmptyScreens();
             mStripScreensOnPageStopMoving = false;
         }
-
-        if (mShouldSendPageSettled) {
-            mLauncherOverlay.onScrollSettled();
-            mShouldSendPageSettled = false;
-        }
     }
 
     protected void onScrollInteractionBegin() {
@@ -1256,6 +1255,47 @@
 
     public void setLauncherOverlay(LauncherOverlay overlay) {
         mLauncherOverlay = overlay;
+        // A new overlay has been set. Reset event tracking
+        mStartedSendingScrollEvents = false;
+        onOverlayScrollChanged(0);
+    }
+
+    @Override
+    protected int getUnboundedScrollX() {
+        if (isScrollingOverlay()) {
+            return mUnboundedScrollX;
+        }
+
+        return super.getUnboundedScrollX();
+    }
+
+    private boolean isScrollingOverlay() {
+        return mLauncherOverlay != null &&
+                ((mIsRtl && mUnboundedScrollX > mMaxScrollX) || (!mIsRtl && mUnboundedScrollX < 0));
+    }
+
+    @Override
+    protected void snapToDestination() {
+        // If we're overscrolling the overlay, we make sure to immediately reset the PagedView
+        // to it's baseline position instead of letting the overscroll settle. The overlay handles
+        // it's own settling, and every gesture to the overlay should be self-contained and start
+        // from 0, so we zero it out here.
+        if (isScrollingOverlay()) {
+            int finalScroll = mIsRtl ? mMaxScrollX : 0;
+
+            // We reset mWasInOverscroll so that PagedView doesn't zero out the overscroll
+            // interaction when we call scrollTo.
+            mWasInOverscroll = false;
+            scrollTo(finalScroll, getScrollY());
+        } else {
+            super.snapToDestination();
+        }
+    }
+
+    @Override
+    public void scrollTo(int x, int y) {
+        mUnboundedScrollX = x;
+        super.scrollTo(x, y);
     }
 
     @Override
@@ -1273,15 +1313,10 @@
             if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
                 mStartedSendingScrollEvents = true;
                 mLauncherOverlay.onScrollInteractionBegin();
-                mShouldSendPageSettled = true;
             }
-            int screenSize = getViewportWidth();
-            float f = (amount / screenSize);
 
-            int progress = (int) Math.abs((f * 100));
-
-            mLastOverlaySroll = progress;
-            mLauncherOverlay.onScrollChange(progress, mIsRtl);
+            mLastOverlaySroll = Math.abs(amount / getViewportWidth());
+            mLauncherOverlay.onScrollChange(mLastOverlaySroll, mIsRtl);
         } else if (shouldOverScroll) {
             dampedOverScroll(amount);
         }
@@ -1291,6 +1326,62 @@
         }
     }
 
+    private final Interpolator mAlphaInterpolator = new DecelerateInterpolator(3f);
+
+    /**
+     * The overlay scroll is being controlled locally, just update our overlay effect
+     */
+    public void onOverlayScrollChanged(float scroll) {
+        float offset = 0f;
+        float slip = 0f;
+
+        scroll = Math.max(scroll - offset, 0);
+        scroll = Math.min(1, scroll / (1 - offset));
+
+        float alpha = 1 - mAlphaInterpolator.getInterpolation(scroll);
+        float transX = mLauncher.getDragLayer().getMeasuredWidth() * scroll;
+        transX *= 1 - slip;
+
+        if (mIsRtl) {
+            transX = -transX;
+        }
+        mOverlayTranslation = transX;
+
+        // TODO(adamcohen): figure out a final effect here. We may need to recommend
+        // different effects based on device performance. On at least one relatively high-end
+        // device I've tried, translating the launcher causes things to get quite laggy.
+        setTranslationAndAlpha(mLauncher.getSearchDropTargetBar(), transX, alpha);
+        setTranslationAndAlpha(getPageIndicator(), transX, alpha);
+        setTranslationAndAlpha(getChildAt(getCurrentPage()), transX, alpha);
+        setTranslationAndAlpha(mLauncher.getHotseat(), transX, alpha);
+
+        // When the animation finishes, reset all pages, just in case we missed a page.
+        if (transX == 0) {
+            for (int i = getChildCount() - 1; i >= 0; i--) {
+                setTranslationAndAlpha(getChildAt(i), 0, alpha);
+            }
+        }
+    }
+
+    @Override
+    protected Matrix getPageShiftMatrix() {
+        if (Float.compare(mOverlayTranslation, 0) != 0) {
+            // The pages are translated by mOverlayTranslation. incorporate that in the
+            // visible page calculation by shifting everything back by that same amount.
+            mTempMatrix.set(getMatrix());
+            mTempMatrix.postTranslate(-mOverlayTranslation, 0);
+            return mTempMatrix;
+        }
+        return super.getPageShiftMatrix();
+    }
+
+    private void setTranslationAndAlpha(View v, float transX, float alpha) {
+        if (v != null) {
+            v.setTranslationX(transX);
+            v.setAlpha(alpha);
+        }
+    }
+
     @Override
     protected void getEdgeVerticalPostion(int[] pos) {
         View child = getChildAt(getPageCount() - 1);
@@ -2017,10 +2108,16 @@
         Animator workspaceAnim =  mStateTransitionAnimation.getAnimationToState(mState,
                 toState, toPage, animated, layerViews);
 
+        boolean shouldNotifyWidgetChange = !mState.shouldUpdateWidget
+                && toState.shouldUpdateWidget;
         // Update the current state
         mState = toState;
         updateAccessibilityFlags();
 
+        if (shouldNotifyWidgetChange) {
+            mLauncher.notifyWidgetProvidersChanged();
+        }
+
         return workspaceAnim;
     }
 
@@ -4160,41 +4257,10 @@
         });
     }
 
-    public void disableShortcutsByPackageName(final ArrayList<String> packages,
-            final UserHandleCompat user, final int reason) {
-        final HashSet<String> packageNames = new HashSet<String>();
-        packageNames.addAll(packages);
-
-        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
-                            && packageNames.contains(cn.getPackageName())) {
-                        shortcutInfo.isDisabled |= reason;
-                        BubbleTextView shortcut = (BubbleTextView) v;
-                        shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache);
-
-                        if (parent != null) {
-                            parent.invalidate();
-                        }
-                    }
-                }
-                // 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, final UserHandleCompat user) {
-        final HashSet<String> packageNames = new HashSet<String>();
-        packageNames.addAll(packages);
-
+    void removeItemsByPackageName(final HashSet<String> packageNames, final UserHandleCompat user) {
         // Filter out all the ItemInfos that this is going to affect
         final HashSet<ItemInfo> infos = new HashSet<ItemInfo>();
         final HashSet<ComponentName> cns = new HashSet<ComponentName>();
@@ -4376,7 +4442,7 @@
     }
 
     public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
-        ArrayList<String> packages = new ArrayList<String>(1);
+        HashSet<String> packages = new HashSet<>(1);
         packages.add(packageName);
         LauncherModel.deletePackageFromDatabase(mLauncher, packageName, user);
         removeItemsByPackageName(packages, user);
@@ -4400,13 +4466,22 @@
         });
     }
 
-    void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
+    public void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
         if (!changedInfo.isEmpty()) {
             DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
                     mLauncher.getAppWidgetHost());
-            if (LauncherModel.getProviderInfo(getContext(),
-                    changedInfo.get(0).providerName,
-                    changedInfo.get(0).user) != null) {
+
+            LauncherAppWidgetInfo item = changedInfo.get(0);
+            final AppWidgetProviderInfo widgetInfo;
+            if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
+                widgetInfo = AppWidgetManagerCompat
+                        .getInstance(mLauncher).findProvider(item.providerName, item.user);
+            } else {
+                widgetInfo = AppWidgetManagerCompat.getInstance(mLauncher)
+                        .getAppWidgetInfo(item.appWidgetId);
+            }
+
+            if (widgetInfo != null) {
                 // Re-inflate the widgets which have changed status
                 widgetRefresh.run();
             } else {
@@ -4493,7 +4568,11 @@
             }
             nScreens--;
         }
-        return String.format(getContext().getString(R.string.workspace_scroll_format),
+        if (nScreens == 0) {
+            // When the workspace is not loaded, we do not know how many screen will be bound.
+            return getContext().getString(R.string.all_apps_home_button_label);
+        }
+        return getContext().getString(R.string.workspace_scroll_format,
                 page + 1 - delta, nScreens);
 
     }
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d41224a..42a395d 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -24,12 +24,16 @@
 import android.graphics.Paint;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat;
 import android.support.v4.view.accessibility.AccessibilityRecordCompat;
 import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.net.Uri;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Recycler;
+import android.support.v7.widget.RecyclerView.State;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -40,10 +44,8 @@
 import com.android.launcher3.AppInfo;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.util.Thunk;
 
 import java.util.HashMap;
 import java.util.List;
@@ -103,18 +105,69 @@
             // adapter views
             final AccessibilityRecordCompat record = AccessibilityEventCompat
                     .asRecord(event);
+
+            // count the number of SECTION_BREAK_VIEW_TYPE that is wrongfully
+            // initialized as a node (also a row) for talk back.
+            int numEmptyNode = getEmptyRowForAccessibility(-1 /* no view type */);
+            record.setFromIndex(event.getFromIndex() - numEmptyNode);
+            record.setToIndex(event.getToIndex() - numEmptyNode);
             record.setItemCount(mApps.getNumFilteredApps());
         }
 
         @Override
+        public void onInitializeAccessibilityNodeInfoForItem(Recycler recycler,
+                State state, View host, AccessibilityNodeInfoCompat info) {
+
+            int viewType = getItemViewType(host);
+            // Only initialize on node that is meaningful. Subtract empty row count.
+            if (viewType == ICON_VIEW_TYPE || viewType == PREDICTION_ICON_VIEW_TYPE) {
+                super.onInitializeAccessibilityNodeInfoForItem(recycler, state, host, info);
+                CollectionItemInfoCompat itemInfo = info.getCollectionItemInfo();
+                if (itemInfo != null) {
+                    final CollectionItemInfoCompat dstItemInfo = CollectionItemInfoCompat.obtain(
+                            itemInfo.getRowIndex() - getEmptyRowForAccessibility(viewType),
+                            itemInfo.getRowSpan(),
+                            itemInfo.getColumnIndex(),
+                            itemInfo.getColumnSpan(),
+                            itemInfo.isHeading(),
+                            itemInfo.isSelected());
+                    info.setCollectionItemInfo(dstItemInfo);
+                }
+            }
+        }
+
+        @Override
         public int getRowCountForAccessibility(RecyclerView.Recycler recycler,
                 RecyclerView.State state) {
-            if (mApps.hasNoFilteredResults()) {
-                // Disregard the no-search-results text as a list item for accessibility
-                return 0;
+            return super.getRowCountForAccessibility(recycler, state)
+                    - getEmptyRowForAccessibility(-1 /* no view type */);
+        }
+
+        /**
+         * Returns the total number of SECTION_BREAK_VIEW_TYPE that is wrongfully
+         * initialized as a node (also a row) for talk back.
+         */
+        private int getEmptyRowForAccessibility(int viewType) {
+            int numEmptyNode = 0;
+            if (mApps.hasFilter()) {
+                // search result screen has only one SECTION_BREAK_VIEW
+                numEmptyNode = 1;
             } else {
-                return super.getRowCountForAccessibility(recycler, state);
+                // default all apps screen may have one or two SECTION_BREAK_VIEW
+                numEmptyNode = 1;
+                if (mApps.hasPredictedComponents()) {
+                    if (viewType == PREDICTION_ICON_VIEW_TYPE) {
+                        numEmptyNode = 1;
+                    } else if (viewType == ICON_VIEW_TYPE) {
+                        numEmptyNode = 2;
+                    }
+                } else {
+                    if (viewType == ICON_VIEW_TYPE) {
+                        numEmptyNode = 1;
+                    }
+                }
             }
+            return numEmptyNode;
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 26e9231..b533ce9 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -275,6 +275,10 @@
         return (mSearchResults != null) && mFilteredApps.isEmpty();
     }
 
+    public boolean hasPredictedComponents() {
+        return (mPredictedAppComponents != null && mPredictedAppComponents.size() > 0);
+    }
+
     /**
      * Sets the sorted list of filtered components.
      */
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index ec1fb66..13ed1a2 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -1,113 +1,49 @@
 package com.android.launcher3.compat;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.util.Log;
+
 import com.android.launcher3.Utilities;
 
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.util.Locale;
 
-/**
- * Fallback class to support Alphabetic indexing if not supported by the framework.
- * TODO(winsonc): disable for non-english locales
- */
-class BaseAlphabeticIndex {
-
-    private static final String BUCKETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-";
-    private static final int UNKNOWN_BUCKET_INDEX = BUCKETS.length() - 1;
-
-    public BaseAlphabeticIndex() {}
-
-    /**
-     * Sets the max number of the label buckets in this index.
-     */
-    public void setMaxLabelCount(int count) {
-        // Not currently supported
-    }
-
-    /**
-     * Returns the index of the bucket in which the given string should appear.
-     */
-    protected int getBucketIndex(String s) {
-        if (s.isEmpty()) {
-            return UNKNOWN_BUCKET_INDEX;
-        }
-        int index = BUCKETS.indexOf(s.substring(0, 1).toUpperCase());
-        if (index != -1) {
-            return index;
-        }
-        return UNKNOWN_BUCKET_INDEX;
-    }
-
-    /**
-     * Returns the label for the bucket at the given index (as returned by getBucketIndex).
-     */
-    protected String getBucketLabel(int index) {
-        return BUCKETS.substring(index, index + 1);
-    }
-}
-
-/**
- * Reflected libcore.icu.AlphabeticIndex implementation, falls back to the base alphabetic index.
- */
-public class AlphabeticIndexCompat extends BaseAlphabeticIndex {
+public class AlphabeticIndexCompat {
+    private static final String TAG = "AlphabeticIndexCompat";
 
     private static final String MID_DOT = "\u2219";
-
-    private Object mAlphabeticIndex;
-    private Method mAddLabelsMethod;
-    private Method mSetMaxLabelCountMethod;
-    private Method mGetBucketIndexMethod;
-    private Method mGetBucketLabelMethod;
-    private boolean mHasValidAlphabeticIndex;
-    private String mDefaultMiscLabel;
+    private final BaseIndex mBaseIndex;
+    private final String mDefaultMiscLabel;
 
     public AlphabeticIndexCompat(Context context) {
-        super();
-        try {
-            Locale curLocale = context.getResources().getConfiguration().locale;
-            Class clazz = Class.forName("libcore.icu.AlphabeticIndex");
-            Constructor ctor = clazz.getConstructor(Locale.class);
-            mAddLabelsMethod = clazz.getDeclaredMethod("addLabels", Locale.class);
-            mSetMaxLabelCountMethod = clazz.getDeclaredMethod("setMaxLabelCount", int.class);
-            mGetBucketIndexMethod = clazz.getDeclaredMethod("getBucketIndex", String.class);
-            mGetBucketLabelMethod = clazz.getDeclaredMethod("getBucketLabel", int.class);
-            mAlphabeticIndex = ctor.newInstance(curLocale);
-            try {
-                // Ensure we always have some base English locale buckets
-                if (!curLocale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
-                    mAddLabelsMethod.invoke(mAlphabeticIndex, Locale.ENGLISH);
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-            if (curLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
-                // Japanese character 他 ("misc")
-                mDefaultMiscLabel = "\u4ed6";
-                // TODO(winsonc, omakoto): We need to handle Japanese sections better, especially the kanji
-            } else {
-                // Dot
-                mDefaultMiscLabel = MID_DOT;
-            }
-            mHasValidAlphabeticIndex = true;
-        } catch (Exception e) {
-            mHasValidAlphabeticIndex = false;
-        }
-    }
+        BaseIndex index = null;
 
-    /**
-     * Sets the max number of the label buckets in this index.
-     * (ICU 51 default is 99)
-     */
-    public void setMaxLabelCount(int count) {
-        if (mHasValidAlphabeticIndex) {
-            try {
-                mSetMaxLabelCountMethod.invoke(mAlphabeticIndex, count);
-            } catch (Exception e) {
-                e.printStackTrace();
+        try {
+            if (Utilities.isNycOrAbove()) {
+                index = new AlphabeticIndexVN(context);
             }
+        } catch (Exception e) {
+            Log.d(TAG, "Unable to load the system index", e);
+        }
+        if (index == null) {
+            try {
+                index = new AlphabeticIndexV16(context);
+            } catch (Exception e) {
+                Log.d(TAG, "Unable to load the system index", e);
+            }
+        }
+
+        mBaseIndex = index == null ? new BaseIndex() : index;
+
+        if (context.getResources().getConfiguration().locale
+                .getLanguage().equals(Locale.JAPANESE.getLanguage())) {
+            // Japanese character 他 ("misc")
+            mDefaultMiscLabel = "\u4ed6";
+            // TODO(winsonc, omakoto): We need to handle Japanese sections better, especially the kanji
         } else {
-            super.setMaxLabelCount(count);
+            // Dot
+            mDefaultMiscLabel = MID_DOT;
         }
     }
 
@@ -116,7 +52,7 @@
      */
     public String computeSectionName(CharSequence cs) {
         String s = Utilities.trim(cs);
-        String sectionName = getBucketLabel(getBucketIndex(s));
+        String sectionName = mBaseIndex.getBucketLabel(mBaseIndex.getBucketIndex(s));
         if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
             int c = s.codePointAt(0);
             boolean startsWithDigit = Character.isDigit(c);
@@ -139,32 +75,150 @@
     }
 
     /**
-     * Returns the index of the bucket in which {@param s} should appear.
-     * Function is synchronized because underlying routine walks an iterator
-     * whose state is maintained inside the index object.
+     * Base class to support Alphabetic indexing if not supported by the framework.
+     * TODO(winsonc): disable for non-english locales
      */
-    protected int getBucketIndex(String s) {
-        if (mHasValidAlphabeticIndex) {
+    private static class BaseIndex {
+
+        private static final String BUCKETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-";
+        private static final int UNKNOWN_BUCKET_INDEX = BUCKETS.length() - 1;
+
+        /**
+         * Returns the index of the bucket in which the given string should appear.
+         */
+        protected int getBucketIndex(String s) {
+            if (s.isEmpty()) {
+                return UNKNOWN_BUCKET_INDEX;
+            }
+            int index = BUCKETS.indexOf(s.substring(0, 1).toUpperCase());
+            if (index != -1) {
+                return index;
+            }
+            return UNKNOWN_BUCKET_INDEX;
+        }
+
+        /**
+         * Returns the label for the bucket at the given index (as returned by getBucketIndex).
+         */
+        protected String getBucketLabel(int index) {
+            return BUCKETS.substring(index, index + 1);
+        }
+    }
+
+    /**
+     * Reflected libcore.icu.AlphabeticIndex implementation, falls back to the base
+     * alphabetic index.
+     */
+    private static class AlphabeticIndexV16 extends BaseIndex {
+
+        private Object mAlphabeticIndex;
+        private Method mGetBucketIndexMethod;
+        private Method mGetBucketLabelMethod;
+
+        public AlphabeticIndexV16(Context context) throws Exception {
+            Locale curLocale = context.getResources().getConfiguration().locale;
+            Class clazz = Class.forName("libcore.icu.AlphabeticIndex");
+            mGetBucketIndexMethod = clazz.getDeclaredMethod("getBucketIndex", String.class);
+            mGetBucketLabelMethod = clazz.getDeclaredMethod("getBucketLabel", int.class);
+            mAlphabeticIndex = clazz.getConstructor(Locale.class).newInstance(curLocale);
+
+            if (!curLocale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
+                clazz.getDeclaredMethod("addLabels", Locale.class)
+                        .invoke(mAlphabeticIndex, Locale.ENGLISH);
+            }
+        }
+
+        /**
+         * Returns the index of the bucket in which {@param s} should appear.
+         * Function is synchronized because underlying routine walks an iterator
+         * whose state is maintained inside the index object.
+         */
+        protected int getBucketIndex(String s) {
             try {
                 return (Integer) mGetBucketIndexMethod.invoke(mAlphabeticIndex, s);
             } catch (Exception e) {
                 e.printStackTrace();
             }
+            return super.getBucketIndex(s);
         }
-        return super.getBucketIndex(s);
-    }
 
-    /**
-     * Returns the label for the bucket at the given index (as returned by getBucketIndex).
-     */
-    protected String getBucketLabel(int index) {
-        if (mHasValidAlphabeticIndex) {
+        /**
+         * Returns the label for the bucket at the given index (as returned by getBucketIndex).
+         */
+        protected String getBucketLabel(int index) {
             try {
                 return (String) mGetBucketLabelMethod.invoke(mAlphabeticIndex, index);
             } catch (Exception e) {
                 e.printStackTrace();
             }
+            return super.getBucketLabel(index);
         }
-        return super.getBucketLabel(index);
+    }
+
+    /**
+     * Reflected android.icu.text.AlphabeticIndex implementation, falls back to the base
+     * alphabetic index.
+     */
+    private static class AlphabeticIndexVN extends BaseIndex {
+
+        private Object mAlphabeticIndex;
+        private Method mGetBucketIndexMethod;
+
+        private Method mGetBucketMethod;
+        private Method mGetLabelMethod;
+
+        public AlphabeticIndexVN(Context context) throws Exception {
+            // TODO: Replace this with locale list once available.
+            Object locales = Configuration.class.getDeclaredMethod("getLocales").invoke(
+                    context.getResources().getConfiguration());
+            int localeCount = (Integer) locales.getClass().getDeclaredMethod("size").invoke(locales);
+            Method localeGetter = locales.getClass().getDeclaredMethod("get", int.class);
+            Locale primaryLocale = localeCount == 0 ? Locale.ENGLISH :
+                    (Locale) localeGetter.invoke(locales, 0);
+
+            Class clazz = Class.forName("android.icu.text.AlphabeticIndex");
+            mAlphabeticIndex = clazz.getConstructor(Locale.class).newInstance(primaryLocale);
+
+            Method addLocales = clazz.getDeclaredMethod("addLabels", Locale[].class);
+            for (int i = 1; i < localeCount; i++) {
+                Locale l = (Locale) localeGetter.invoke(locales, i);
+                addLocales.invoke(mAlphabeticIndex, new Object[]{ new Locale[] {l}});
+            }
+            addLocales.invoke(mAlphabeticIndex, new Object[]{ new Locale[] {Locale.ENGLISH}});
+
+            mAlphabeticIndex = mAlphabeticIndex.getClass()
+                    .getDeclaredMethod("buildImmutableIndex")
+                    .invoke(mAlphabeticIndex);
+
+            mGetBucketIndexMethod = mAlphabeticIndex.getClass().getDeclaredMethod(
+                    "getBucketIndex", CharSequence.class);
+            mGetBucketMethod = mAlphabeticIndex.getClass().getDeclaredMethod("getBucket", int.class);
+            mGetLabelMethod = mGetBucketMethod.getReturnType().getDeclaredMethod("getLabel");
+        }
+
+        /**
+         * Returns the index of the bucket in which {@param s} should appear.
+         */
+        protected int getBucketIndex(String s) {
+            try {
+                return (Integer) mGetBucketIndexMethod.invoke(mAlphabeticIndex, s);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return super.getBucketIndex(s);
+        }
+
+        /**
+         * Returns the label for the bucket at the given index
+         */
+        protected String getBucketLabel(int index) {
+            try {
+                return (String) mGetLabelMethod.invoke(
+                        mGetBucketMethod.invoke(mAlphabeticIndex, index));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return super.getBucketLabel(index);
+        }
     }
 }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
index f0221bc..811cacf 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -20,6 +20,7 @@
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
@@ -28,7 +29,9 @@
 import com.android.launcher3.IconCache;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.ComponentKey;
 
+import java.util.HashMap;
 import java.util.List;
 
 public abstract class AppWidgetManagerCompat {
@@ -62,6 +65,11 @@
         return mAppWidgetManager.getAppWidgetInfo(appWidgetId);
     }
 
+    public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(int appWidgetId) {
+        AppWidgetProviderInfo info = getAppWidgetInfo(appWidgetId);
+        return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
+    }
+
     public abstract List<AppWidgetProviderInfo> getAllProviders();
 
     public abstract String loadLabel(LauncherAppWidgetProviderInfo info);
@@ -81,4 +89,8 @@
     public abstract Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
             int imageWidth, int imageHeight);
 
+    public abstract LauncherAppWidgetProviderInfo findProvider(
+            ComponentName provider, UserHandleCompat user);
+
+    public abstract HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap();
 }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
index e9d2510..de9414e 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
@@ -21,6 +21,7 @@
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -31,7 +32,9 @@
 import com.android.launcher3.IconCache;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.ComponentKey;
 
+import java.util.HashMap;
 import java.util.List;
 
 class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
@@ -91,4 +94,25 @@
             int imageWidth, int imageHeight) {
         return bitmap;
     }
+
+    @Override
+    public LauncherAppWidgetProviderInfo findProvider(
+            ComponentName provider, UserHandleCompat user) {
+        for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProviders()) {
+            if (info.provider.equals(provider)) {
+                return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap() {
+        HashMap<ComponentKey, AppWidgetProviderInfo> result = new HashMap<>();
+        UserHandleCompat user = UserHandleCompat.myUserHandle();
+        for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProviders()) {
+            result.put(new ComponentKey(info.provider, user), info);
+        }
+        return result;
+    }
 }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
index 3bc3d0d..a1570e6 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -21,6 +21,7 @@
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
@@ -40,8 +41,10 @@
 import com.android.launcher3.IconCache;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.R;
+import com.android.launcher3.util.ComponentKey;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@@ -145,4 +148,28 @@
         c.setBitmap(null);
         return bitmap;
     }
+
+    @Override
+    public LauncherAppWidgetProviderInfo findProvider(ComponentName provider, UserHandleCompat user) {
+        for (AppWidgetProviderInfo info : mAppWidgetManager
+                .getInstalledProvidersForProfile(user.getUser())) {
+            if (info.provider.equals(provider)) {
+                return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap() {
+        HashMap<ComponentKey, AppWidgetProviderInfo> result = new HashMap<>();
+        for (UserHandle user : mUserManager.getUserProfiles()) {
+            UserHandleCompat userHandle = UserHandleCompat.fromUser(user);
+            for (AppWidgetProviderInfo info :
+                    mAppWidgetManager.getInstalledProvidersForProfile(user)) {
+                result.put(new ComponentKey(info.provider, userHandle), info);
+            }
+        }
+        return result;
+    }
 }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 95e3ba9..237a9e9 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -19,9 +19,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Rect;
 import android.os.Bundle;
 
@@ -35,6 +32,10 @@
             "android.intent.action.MANAGED_PROFILE_ADDED";
     public static final String ACTION_MANAGED_PROFILE_REMOVED =
             "android.intent.action.MANAGED_PROFILE_REMOVED";
+    public static final String ACTION_MANAGED_PROFILE_AVAILABLE =
+            "android.intent.action.MANAGED_PROFILE_AVAILABLE";
+    public static final String ACTION_MANAGED_PROFILE_UNAVAILABLE =
+            "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
 
     public interface OnAppsChangedCallbackCompat {
         void onPackageRemoved(String packageName, UserHandleCompat user);
@@ -42,6 +43,8 @@
         void onPackageChanged(String packageName, UserHandleCompat user);
         void onPackagesAvailable(String[] packageNames, UserHandleCompat user, boolean replacing);
         void onPackagesUnavailable(String[] packageNames, UserHandleCompat user, boolean replacing);
+        void onPackagesSuspended(String[] packageNames, UserHandleCompat user);
+        void onPackagesUnsuspended(String[] packageNames, UserHandleCompat user);
     }
 
     protected LauncherAppsCompat() {
@@ -75,13 +78,5 @@
     public abstract boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user);
     public abstract boolean isActivityEnabledForProfile(ComponentName component,
             UserHandleCompat user);
-
-    public boolean isAppEnabled(PackageManager pm, String packageName, int flags) {
-        try {
-            ApplicationInfo info = pm.getApplicationInfo(packageName, flags);
-            return info != null && info.enabled;
-        } catch (NameNotFoundException e) {
-            return false;
-        }
-    }
-}
\ No newline at end of file
+    public abstract boolean isPackageSuspendedForProfile(String packageName, UserHandleCompat user);
+}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
index 339c457..4e2fc05 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
@@ -27,11 +27,11 @@
 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 com.android.launcher3.Utilities;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Thunk;
 
 import java.util.ArrayList;
@@ -114,7 +114,7 @@
     }
 
     public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
-        return isAppEnabled(mPm, packageName, 0);
+        return PackageManagerHelper.isAppEnabled(mPm, packageName);
     }
 
     public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
@@ -126,6 +126,10 @@
         }
     }
 
+    public boolean isPackageSuspendedForProfile(String packageName, UserHandleCompat user) {
+        return false;
+    }
+
     private void unregisterForPackageIntents() {
         mContext.unregisterReceiver(mPackageMonitor);
     }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index fbf91b5..7270d02 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -36,7 +36,7 @@
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public class LauncherAppsCompatVL extends LauncherAppsCompat {
 
-    private LauncherApps mLauncherApps;
+    protected LauncherApps mLauncherApps;
 
     private Map<OnAppsChangedCallbackCompat, WrappedCallback> mCallbacks
             = new HashMap<OnAppsChangedCallbackCompat, WrappedCallback>();
@@ -106,6 +106,10 @@
         return mLauncherApps.isActivityEnabled(component, user.getUser());
     }
 
+    public boolean isPackageSuspendedForProfile(String packageName, UserHandleCompat user) {
+        return false;
+    }
+
     private static class WrappedCallback extends LauncherApps.Callback {
         private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
 
@@ -134,6 +138,14 @@
             mCallback.onPackagesUnavailable(packageNames, UserHandleCompat.fromUser(user),
                     replacing);
         }
+
+        public void onPackagesSuspended(String[] packageNames, UserHandle user) {
+            mCallback.onPackagesSuspended(packageNames, UserHandleCompat.fromUser(user));
+        }
+
+        public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
+            mCallback.onPackagesUnsuspended(packageNames, UserHandleCompat.fromUser(user));
+        }
     }
 }
 
diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java
index 9479908..50af21b 100644
--- a/src/com/android/launcher3/compat/UserHandleCompat.java
+++ b/src/com/android/launcher3/compat/UserHandleCompat.java
@@ -93,4 +93,14 @@
             intent.putExtra(name, mUser);
         }
     }
+
+    public static UserHandleCompat fromIntent(Intent intent) {
+        if (Utilities.ATLEAST_LOLLIPOP) {
+            UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
+            if (user != null) {
+                return UserHandleCompat.fromUser(user);
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index 6b7cba8..978f922 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -32,7 +32,9 @@
     public static UserManagerCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
             if (sInstance == null) {
-                if (Utilities.ATLEAST_LOLLIPOP) {
+                if (Utilities.isNycOrAbove()) {
+                    sInstance = new UserManagerCompatVN(context.getApplicationContext());
+                } else if (Utilities.ATLEAST_LOLLIPOP) {
                     sInstance = new UserManagerCompatVL(context.getApplicationContext());
                 } else if (Utilities.ATLEAST_JB_MR1) {
                     sInstance = new UserManagerCompatV17(context.getApplicationContext());
@@ -54,4 +56,5 @@
     public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
     public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user);
     public abstract long getUserCreationTime(UserHandleCompat user);
+    public abstract boolean isQuietModeEnabled(UserHandleCompat user);
 }
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV16.java b/src/com/android/launcher3/compat/UserManagerCompatV16.java
index fcd7555..a006efd 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV16.java
@@ -50,4 +50,9 @@
     @Override
     public void enableAndResetCache() {
     }
+
+    @Override
+    public boolean isQuietModeEnabled(UserHandleCompat user) {
+        return false;
+    }
 }
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVN.java b/src/com/android/launcher3/compat/UserManagerCompatVN.java
new file mode 100644
index 0000000..ae41e68
--- /dev/null
+++ b/src/com/android/launcher3/compat/UserManagerCompatVN.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+//TODO: Once gogole3 SDK is updated to N, add @TargetApi(Build.VERSION_CODES.N)
+public class UserManagerCompatVN extends UserManagerCompatVL {
+
+    private static final String TAG = "UserManagerCompatVN";
+
+    UserManagerCompatVN(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean isQuietModeEnabled(UserHandleCompat user) {
+        if (user != null) {
+            try {
+                //TODO: Replace with proper API call once google3 SDK is updated.
+                Method isQuietModeEnabledMethod = UserManager.class.getMethod("isQuietModeEnabled",
+                        UserHandle.class);
+                return (boolean) isQuietModeEnabledMethod.invoke(mUserManager, user.getUser());
+            } catch (NoSuchMethodError | NoSuchMethodException | IllegalAccessException
+                    | InvocationTargetException e) {
+                Log.e(TAG, "Running on N without isQuietModeEnabled", e);
+            } catch (IllegalArgumentException e) {
+                // TODO remove this when API is fixed to not throw this
+                // when called on user that isn't a managed profile.
+            }
+        }
+        return false;
+    }
+}
+
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
new file mode 100644
index 0000000..8117122
--- /dev/null
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -0,0 +1,1030 @@
+package com.android.launcher3.model;
+
+import android.content.ComponentName;
+import android.content.ContentProviderOperation;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.database.Cursor;
+import android.graphics.Point;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.backup.nano.BackupProtos;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.util.LongArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+
+/**
+ * This class takes care of shrinking the workspace (by maximum of one row and one column), as a
+ * result of restoring from a larger device or device density change.
+ */
+public class GridSizeMigrationTask {
+
+    public static boolean ENABLED = Utilities.isNycOrAbove();
+
+    private static final String TAG = "GridSizeMigrationTask";
+    private static final boolean DEBUG = true;
+
+    private static final String KEY_MIGRATION_SRC_WORKSPACE_SIZE = "migration_src_workspace_size";
+    private static final String KEY_MIGRATION_SRC_HOTSEAT_SIZE = "migration_src_hotseat_size";
+
+    // Set of entries indicating minimum size a widget can be resized to. This is used during
+    // restore in case the widget has not been installed yet.
+    private static final String KEY_MIGRATION_WIDGET_MINSIZE = "migration_widget_min_size";
+
+    // These are carefully selected weights for various item types (Math.random?), to allow for
+    // the least absurd migration experience.
+    private static final float WT_SHORTCUT = 1;
+    private static final float WT_APPLICATION = 0.8f;
+    private static final float WT_WIDGET_MIN = 2;
+    private static final float WT_WIDGET_FACTOR = 0.6f;
+    private static final float WT_FOLDER_FACTOR = 0.5f;
+
+    private final Context mContext;
+    private final InvariantDeviceProfile mIdp;
+
+    private final HashMap<String, Point> mWidgetMinSize = new HashMap<>();
+    private final ContentValues mTempValues = new ContentValues();
+    private final ArrayList<Long> mEntryToRemove = new ArrayList<>();
+    private final ArrayList<ContentProviderOperation> mUpdateOperations = new ArrayList<>();
+    private final ArrayList<DbEntry> mCarryOver = new ArrayList<>();
+    private final HashSet<String> mValidPackages;
+
+    private final int mSrcX, mSrcY;
+    private final int mTrgX, mTrgY;
+    private final boolean mShouldRemoveX, mShouldRemoveY;
+
+    private final int mSrcHotseatSize;
+    private final int mSrcAllAppsRank;
+    private final int mDestHotseatSize;
+    private final int mDestAllAppsRank;
+
+    protected GridSizeMigrationTask(Context context, InvariantDeviceProfile idp,
+            HashSet<String> validPackages, HashMap<String, Point> widgetMinSize,
+            Point sourceSize, Point targetSize) {
+        mContext = context;
+        mValidPackages = validPackages;
+        mWidgetMinSize.putAll(widgetMinSize);
+        mIdp = idp;
+
+        mSrcX = sourceSize.x;
+        mSrcY = sourceSize.y;
+
+        mTrgX = targetSize.x;
+        mTrgY = targetSize.y;
+
+        mShouldRemoveX = mTrgX < mSrcX;
+        mShouldRemoveY = mTrgY < mSrcY;
+
+        // Non-used variables
+        mSrcHotseatSize = mSrcAllAppsRank = mDestHotseatSize = mDestAllAppsRank = -1;
+    }
+
+    protected GridSizeMigrationTask(Context context,
+            InvariantDeviceProfile idp, HashSet<String> validPackages,
+            int srcHotseatSize, int srcAllAppsRank,
+            int destHotseatSize, int destAllAppsRank) {
+        mContext = context;
+        mIdp = idp;
+        mValidPackages = validPackages;
+
+        mSrcHotseatSize = srcHotseatSize;
+        mSrcAllAppsRank = srcAllAppsRank;
+
+        mDestHotseatSize = destHotseatSize;
+        mDestAllAppsRank = destAllAppsRank;
+
+        // Non-used variables
+        mSrcX = mSrcY = mTrgX = mTrgY = -1;
+        mShouldRemoveX = mShouldRemoveY = false;
+    }
+
+    /**
+     * Applied all the pending DB operations
+     * @return true if any DB operation was commited.
+     */
+    private boolean applyOperations() throws Exception {
+        // Update items
+        if (!mUpdateOperations.isEmpty()) {
+            mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, mUpdateOperations);
+        }
+
+        if (!mEntryToRemove.isEmpty()) {
+            if (DEBUG) {
+                Log.d(TAG, "Removing items: " + TextUtils.join(", ", mEntryToRemove));
+            }
+            mContext.getContentResolver().delete(LauncherSettings.Favorites.CONTENT_URI,
+                    Utilities.createDbSelectionQuery(
+                            LauncherSettings.Favorites._ID, mEntryToRemove), null);
+        }
+
+        return !mUpdateOperations.isEmpty() || !mEntryToRemove.isEmpty();
+    }
+
+    /**
+     * To migrate hotseat, we load all the entries in order (LTR or RTL) and arrange them
+     * in the order in the new hotseat while keeping an empty space for all-apps. If the number of
+     * entries is more than what can fit in the new hotseat, we drop the entries with least weight.
+     * For weight calculation {@see #WT_SHORTCUT}, {@see #WT_APPLICATION}
+     * & {@see #WT_FOLDER_FACTOR}.
+     * @return true if any DB change was made
+     */
+    protected boolean migrateHotseat() throws Exception {
+        ArrayList<DbEntry> items = loadHotseatEntries();
+
+        int requiredCount = mDestHotseatSize - 1;
+
+        while (items.size() > requiredCount) {
+            // Pick the center item by default.
+            DbEntry toRemove = items.get(items.size() / 2);
+
+            // Find the item with least weight.
+            for (DbEntry entry : items) {
+                if (entry.weight < toRemove.weight) {
+                    toRemove = entry;
+                }
+            }
+
+            mEntryToRemove.add(toRemove.id);
+            items.remove(toRemove);
+        }
+
+        // Update screen IDS
+        int newScreenId = 0;
+        for (DbEntry entry : items) {
+            if (entry.screenId != newScreenId) {
+                entry.screenId = newScreenId;
+
+                // These values does not affect the item position, but we should set them
+                // to something other than -1.
+                entry.cellX = newScreenId;
+                entry.cellY = 0;
+
+                update(entry);
+            }
+
+            newScreenId++;
+            if (newScreenId == mDestAllAppsRank) {
+                newScreenId++;
+            }
+        }
+
+        return applyOperations();
+    }
+
+    /**
+     * @return true if any DB change was made
+     */
+    protected boolean migrateWorkspace() throws Exception {
+        ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(mContext);
+        if (allScreens.isEmpty()) {
+            throw new Exception("Unable to get workspace screens");
+        }
+
+        for (long screenId : allScreens) {
+            if (DEBUG) {
+                Log.d(TAG, "Migrating " + screenId);
+            }
+            migrateScreen(screenId);
+        }
+
+        if (!mCarryOver.isEmpty()) {
+            LongArrayMap<DbEntry> itemMap = new LongArrayMap<>();
+            for (DbEntry e : mCarryOver) {
+                itemMap.put(e.id, e);
+            }
+
+            do {
+                // Some items are still remaining. Try adding a few new screens.
+
+                // At every iteration, make sure that at least one item is removed from
+                // {@link #mCarryOver}, to prevent an infinite loop. If no item could be removed,
+                // break the loop and abort migration by throwing an exception.
+                OptimalPlacementSolution placement = new OptimalPlacementSolution(
+                        new boolean[mTrgX][mTrgY], deepCopy(mCarryOver), true);
+                placement.find();
+                if (placement.finalPlacedItems.size() > 0) {
+                    long newScreenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
+                    allScreens.add(newScreenId);
+                    for (DbEntry item : placement.finalPlacedItems) {
+                        if (!mCarryOver.remove(itemMap.get(item.id))) {
+                            throw new Exception("Unable to find matching items");
+                        }
+                        item.screenId = newScreenId;
+                        update(item);
+                    }
+                } else {
+                    throw new Exception("None of the items can be placed on an empty screen");
+                }
+
+            } while (!mCarryOver.isEmpty());
+
+            // Update screens
+            final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
+            mUpdateOperations.add(ContentProviderOperation.newDelete(uri).build());
+            int count = allScreens.size();
+            for (int i = 0; i < count; i++) {
+                ContentValues v = new ContentValues();
+                long screenId = allScreens.get(i);
+                v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
+                v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+                mUpdateOperations.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
+            }
+        }
+        return applyOperations();
+    }
+
+    /**
+     * Migrate a particular screen id.
+     * Strategy:
+     *   1) For all possible combinations of row and column, pick the one which causes the least
+     *      data loss: {@link #tryRemove(int, int, ArrayList, float[])}
+     *   2) Maintain a list of all lost items before this screen, and add any new item lost from
+     *      this screen to that list as well.
+     *   3) If all those items from the above list can be placed on this screen, place them
+     *      (otherwise they are placed on a new screen).
+     */
+    private void migrateScreen(long screenId) {
+        ArrayList<DbEntry> items = loadWorkspaceEntries(screenId);
+
+        int removedCol = Integer.MAX_VALUE;
+        int removedRow = Integer.MAX_VALUE;
+
+        // removeWt represents the cost function for loss of items during migration, and moveWt
+        // represents the cost function for repositioning the items. moveWt is only considered if
+        // removeWt is same for two different configurations.
+        // Start with Float.MAX_VALUE (assuming full data) and pick the configuration with least
+        // cost.
+        float removeWt = Float.MAX_VALUE;
+        float moveWt = Float.MAX_VALUE;
+        float[] outLoss = new float[2];
+        ArrayList<DbEntry> finalItems = null;
+
+        // Try removing all possible combinations
+        for (int x = 0; x < mSrcX; x++) {
+            for (int y = 0; y < mSrcY; y++) {
+                // Use a deep copy when trying out a particular combination as it can change
+                // the underlying object.
+                ArrayList<DbEntry> itemsOnScreen = tryRemove(x, y, deepCopy(items), outLoss);
+
+                if ((outLoss[0] < removeWt) || ((outLoss[0] == removeWt) && (outLoss[1] < moveWt))) {
+                    removeWt = outLoss[0];
+                    moveWt = outLoss[1];
+                    removedCol = mShouldRemoveX ? x : removedCol;
+                    removedRow = mShouldRemoveY ? y : removedRow;
+                    finalItems = itemsOnScreen;
+                }
+
+                // No need to loop over all rows, if a row removal is not needed.
+                if (!mShouldRemoveY) {
+                    break;
+                }
+            }
+
+            if (!mShouldRemoveX) {
+                break;
+            }
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, String.format("Removing row %d, column %d on screen %d",
+                    removedRow, removedCol, screenId));
+        }
+
+        LongArrayMap<DbEntry> itemMap = new LongArrayMap<>();
+        for (DbEntry e : deepCopy(items)) {
+            itemMap.put(e.id, e);
+        }
+
+        for (DbEntry item : finalItems) {
+            DbEntry org = itemMap.get(item.id);
+            itemMap.remove(item.id);
+
+            // Check if update is required
+            if (!item.columnsSame(org)) {
+                update(item);
+            }
+        }
+
+        // The remaining items in {@link #itemMap} are those which didn't get placed.
+        for (DbEntry item : itemMap) {
+            mCarryOver.add(item);
+        }
+
+        if (!mCarryOver.isEmpty() && removeWt == 0) {
+            // No new items were removed in this step. Try placing all the items on this screen.
+            boolean[][] occupied = new boolean[mTrgX][mTrgY];
+            for (DbEntry item : finalItems) {
+                markCells(occupied, item, true);
+            }
+
+            OptimalPlacementSolution placement = new OptimalPlacementSolution(occupied,
+                    deepCopy(mCarryOver), true);
+            placement.find();
+            if (placement.lowestWeightLoss == 0) {
+                // All items got placed
+
+                for (DbEntry item : placement.finalPlacedItems) {
+                    item.screenId = screenId;
+                    update(item);
+                }
+
+                mCarryOver.clear();
+            }
+        }
+    }
+
+    /**
+     * Updates an item in the DB.
+     */
+    private void update(DbEntry item) {
+        mTempValues.clear();
+        item.addToContentValues(mTempValues);
+        mUpdateOperations.add(ContentProviderOperation
+                .newUpdate(LauncherSettings.Favorites.getContentUri(item.id))
+                .withValues(mTempValues).build());
+    }
+
+    /**
+     * Tries the remove the provided row and column.
+     * @param items all the items on the screen under operation
+     * @param outLoss array of size 2. The first entry is filled with weight loss, and the second
+     * with the overall item movement.
+     */
+    private ArrayList<DbEntry> tryRemove(int col, int row, ArrayList<DbEntry> items,
+            float[] outLoss) {
+        boolean[][] occupied = new boolean[mTrgX][mTrgY];
+
+        col = mShouldRemoveX ? col : Integer.MAX_VALUE;
+        row = mShouldRemoveY ? row : Integer.MAX_VALUE;
+
+        ArrayList<DbEntry> finalItems = new ArrayList<>();
+        ArrayList<DbEntry> removedItems = new ArrayList<>();
+
+        for (DbEntry item : items) {
+            if ((item.cellX <= col && (item.spanX + item.cellX) > col)
+                || (item.cellY <= row && (item.spanY + item.cellY) > row)) {
+                removedItems.add(item);
+                if (item.cellX >= col) item.cellX --;
+                if (item.cellY >= row) item.cellY --;
+            } else {
+                if (item.cellX > col) item.cellX --;
+                if (item.cellY > row) item.cellY --;
+                finalItems.add(item);
+                markCells(occupied, item, true);
+            }
+        }
+
+        OptimalPlacementSolution placement = new OptimalPlacementSolution(occupied, removedItems);
+        placement.find();
+        finalItems.addAll(placement.finalPlacedItems);
+        outLoss[0] = placement.lowestWeightLoss;
+        outLoss[1] = placement.lowestMoveCost;
+        return finalItems;
+    }
+
+    private void markCells(boolean[][] occupied, DbEntry item, boolean val) {
+        for (int i = item.cellX; i < (item.cellX + item.spanX); i++) {
+            for (int j = item.cellY; j < (item.cellY + item.spanY); j++) {
+                occupied[i][j] = val;
+            }
+        }
+    }
+
+    private boolean isVacant(boolean[][] occupied, int x, int y, int w, int h) {
+        if (x + w > mTrgX) return false;
+        if (y + h > mTrgY) return false;
+
+        for (int i = 0; i < w; i++) {
+            for (int j = 0; j < h; j++) {
+                if (occupied[i + x][j + y]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private class OptimalPlacementSolution {
+        private final ArrayList<DbEntry> itemsToPlace;
+        private final boolean[][] occupied;
+
+        // If set to true, item movement are not considered in move cost, leading to a more
+        // linear placement.
+        private final boolean ignoreMove;
+
+        float lowestWeightLoss = Float.MAX_VALUE;
+        float lowestMoveCost = Float.MAX_VALUE;
+        ArrayList<DbEntry> finalPlacedItems;
+
+        public OptimalPlacementSolution(boolean[][] occupied, ArrayList<DbEntry> itemsToPlace) {
+            this(occupied, itemsToPlace, false);
+        }
+
+        public OptimalPlacementSolution(boolean[][] occupied, ArrayList<DbEntry> itemsToPlace,
+                boolean ignoreMove) {
+            this.occupied = occupied;
+            this.itemsToPlace = itemsToPlace;
+            this.ignoreMove = ignoreMove;
+
+            // Sort the items such that larger widgets appear first followed by 1x1 items
+            Collections.sort(this.itemsToPlace);
+        }
+
+        public void find() {
+            find(0, 0, 0, new ArrayList<DbEntry>());
+        }
+
+        /**
+         * Recursively finds a placement for the provided items.
+         * @param index the position in {@link #itemsToPlace} to start looking at.
+         * @param weightLoss total weight loss upto this point
+         * @param moveCost total move cost upto this point
+         * @param itemsPlaced all the items already placed upto this point
+         */
+        public void find(int index, float weightLoss, float moveCost,
+                ArrayList<DbEntry> itemsPlaced) {
+            if ((weightLoss >= lowestWeightLoss) ||
+                    ((weightLoss == lowestWeightLoss) && (moveCost >= lowestMoveCost))) {
+                // Abort, as we already have a better solution.
+                return;
+
+            } else if (index >= itemsToPlace.size()) {
+                // End loop.
+                lowestWeightLoss = weightLoss;
+                lowestMoveCost = moveCost;
+
+                // Keep a deep copy of current configuration as it can change during recursion.
+                finalPlacedItems = deepCopy(itemsPlaced);
+                return;
+            }
+
+            DbEntry me = itemsToPlace.get(index);
+            int myX = me.cellX;
+            int myY = me.cellY;
+
+            // List of items to pass over if this item was placed.
+            ArrayList<DbEntry> itemsIncludingMe = new ArrayList<>(itemsPlaced.size() + 1);
+            itemsIncludingMe.addAll(itemsPlaced);
+            itemsIncludingMe.add(me);
+
+            if (me.spanX > 1 || me.spanY > 1) {
+                // If the current item is a widget (and it greater than 1x1), try to place it at
+                // all possible positions. This is because a widget placed at one position can
+                // affect the placement of a different widget.
+                int myW = me.spanX;
+                int myH = me.spanY;
+
+                for (int y = 0; y < mTrgY; y++) {
+                    for (int x = 0; x < mTrgX; x++) {
+                        float newMoveCost = moveCost;
+                        if (x != myX) {
+                            me.cellX = x;
+                            newMoveCost ++;
+                        }
+                        if (y != myY) {
+                            me.cellY = y;
+                            newMoveCost ++;
+                        }
+                        if (ignoreMove) {
+                            newMoveCost = moveCost;
+                        }
+
+                        if (isVacant(occupied, x, y, myW, myH)) {
+                            // place at this position and continue search.
+                            markCells(occupied, me, true);
+                            find(index + 1, weightLoss, newMoveCost, itemsIncludingMe);
+                            markCells(occupied, me, false);
+                        }
+
+                        // Try resizing horizontally
+                        if (myW > me.minSpanX && isVacant(occupied, x, y, myW - 1, myH)) {
+                            me.spanX --;
+                            markCells(occupied, me, true);
+                            // 1 extra move cost
+                            find(index + 1, weightLoss, newMoveCost + 1, itemsIncludingMe);
+                            markCells(occupied, me, false);
+                            me.spanX ++;
+                        }
+
+                        // Try resizing vertically
+                        if (myH > me.minSpanY && isVacant(occupied, x, y, myW, myH - 1)) {
+                            me.spanY --;
+                            markCells(occupied, me, true);
+                            // 1 extra move cost
+                            find(index + 1, weightLoss, newMoveCost + 1, itemsIncludingMe);
+                            markCells(occupied, me, false);
+                            me.spanY ++;
+                        }
+
+                        // Try resizing horizontally & vertically
+                        if (myH > me.minSpanY && myW > me.minSpanX &&
+                                isVacant(occupied, x, y, myW - 1, myH - 1)) {
+                            me.spanX --;
+                            me.spanY --;
+                            markCells(occupied, me, true);
+                            // 2 extra move cost
+                            find(index + 1, weightLoss, newMoveCost + 2, itemsIncludingMe);
+                            markCells(occupied, me, false);
+                            me.spanX ++;
+                            me.spanY ++;
+                        }
+                        me.cellX = myX;
+                        me.cellY = myY;
+                    }
+                }
+
+                // Finally also try a solution when this item is not included. Trying it in the end
+                // causes it to get skipped in most cases due to higher weight loss, and prevents
+                // unnecessary deep copies of various configurations.
+                find(index + 1, weightLoss + me.weight, moveCost, itemsPlaced);
+            } else {
+                // Since this is a 1x1 item and all the following items are also 1x1, just place
+                // it at 'the most appropriate position' and hope for the best.
+                // The most appropriate position: one with lease straight line distance
+                int newDistance = Integer.MAX_VALUE;
+                int newX = Integer.MAX_VALUE, newY = Integer.MAX_VALUE;
+
+                for (int y = 0; y < mTrgY; y++) {
+                    for (int x = 0; x < mTrgX; x++) {
+                        if (!occupied[x][y]) {
+                            int dist = ignoreMove ? 0 :
+                                ((me.cellX - x) * (me.cellX - x) + (me.cellY - y) * (me.cellY - y));
+                            if (dist < newDistance) {
+                                newX = x;
+                                newY = y;
+                                newDistance = dist;
+                            }
+                        }
+                    }
+                }
+
+                if (newX < mTrgX && newY < mTrgY) {
+                    float newMoveCost = moveCost;
+                    if (newX != myX) {
+                        me.cellX = newX;
+                        newMoveCost ++;
+                    }
+                    if (newY != myY) {
+                        me.cellY = newY;
+                        newMoveCost ++;
+                    }
+                    if (ignoreMove) {
+                        newMoveCost = moveCost;
+                    }
+                    markCells(occupied, me, true);
+                    find(index + 1, weightLoss, newMoveCost, itemsIncludingMe);
+                    markCells(occupied, me, false);
+                    me.cellX = myX;
+                    me.cellY = myY;
+
+                    // Try to find a solution without this item, only if
+                    //  1) there was at least one space, i.e., we were able to place this item
+                    //  2) if the next item has the same weight (all items are already sorted), as
+                    //     if it has lower weight, that solution will automatically get discarded.
+                    //  3) ignoreMove false otherwise, move cost is ignored and the weight will
+                    //      anyway be same.
+                    if (index + 1 < itemsToPlace.size()
+                            && itemsToPlace.get(index + 1).weight >= me.weight && !ignoreMove) {
+                        find(index + 1, weightLoss + me.weight, moveCost, itemsPlaced);
+                    }
+                } else {
+                    // No more space. Jump to the end.
+                    for (int i = index + 1; i < itemsToPlace.size(); i++) {
+                        weightLoss += itemsToPlace.get(i).weight;
+                    }
+                    find(itemsToPlace.size(), weightLoss + me.weight, moveCost, itemsPlaced);
+                }
+            }
+        }
+    }
+
+    private ArrayList<DbEntry> loadHotseatEntries() {
+        Cursor c =  mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[]{
+                        Favorites._ID,                  // 0
+                        Favorites.ITEM_TYPE,            // 1
+                        Favorites.INTENT,               // 2
+                        Favorites.SCREEN},              // 3
+                Favorites.CONTAINER + " = " + Favorites.CONTAINER_HOTSEAT, null, null, null);
+
+        final int indexId = c.getColumnIndexOrThrow(Favorites._ID);
+        final int indexItemType = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
+        final int indexIntent = c.getColumnIndexOrThrow(Favorites.INTENT);
+        final int indexScreen = c.getColumnIndexOrThrow(Favorites.SCREEN);
+
+        ArrayList<DbEntry> entries = new ArrayList<>();
+        while (c.moveToNext()) {
+            DbEntry entry = new DbEntry();
+            entry.id = c.getLong(indexId);
+            entry.itemType = c.getInt(indexItemType);
+            entry.screenId = c.getLong(indexScreen);
+
+            if (entry.screenId >= mSrcHotseatSize) {
+                mEntryToRemove.add(entry.id);
+                continue;
+            }
+
+            try {
+                // calculate weight
+                switch (entry.itemType) {
+                    case Favorites.ITEM_TYPE_SHORTCUT:
+                    case Favorites.ITEM_TYPE_APPLICATION: {
+                        verifyIntent(c.getString(indexIntent));
+                        entry.weight = entry.itemType == Favorites.ITEM_TYPE_SHORTCUT
+                                ? WT_SHORTCUT : WT_APPLICATION;
+                        break;
+                    }
+                    case Favorites.ITEM_TYPE_FOLDER: {
+                        int total = getFolderItemsCount(entry.id);
+                        if (total == 0) {
+                            throw new Exception("Folder is empty");
+                        }
+                        entry.weight = WT_FOLDER_FACTOR * total;
+                        break;
+                    }
+                    default:
+                        throw new Exception("Invalid item type");
+                }
+            } catch (Exception e) {
+                if (DEBUG) {
+                    Log.d(TAG, "Removing item " + entry.id, e);
+                }
+                mEntryToRemove.add(entry.id);
+                continue;
+            }
+            entries.add(entry);
+        }
+        c.close();
+        return entries;
+    }
+
+
+    /**
+     * Loads entries for a particular screen id.
+     */
+    private ArrayList<DbEntry> loadWorkspaceEntries(long screen) {
+        Cursor c =  mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[]{
+                        Favorites._ID,                  // 0
+                        Favorites.ITEM_TYPE,            // 1
+                        Favorites.CELLX,                // 2
+                        Favorites.CELLY,                // 3
+                        Favorites.SPANX,                // 4
+                        Favorites.SPANY,                // 5
+                        Favorites.INTENT,               // 6
+                        Favorites.APPWIDGET_PROVIDER,   // 7
+                        Favorites.APPWIDGET_ID},        // 8
+                Favorites.CONTAINER + " = " + Favorites.CONTAINER_DESKTOP
+                        + " AND " + Favorites.SCREEN + " = " + screen, null, null, null);
+
+        final int indexId = c.getColumnIndexOrThrow(Favorites._ID);
+        final int indexItemType = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
+        final int indexCellX = c.getColumnIndexOrThrow(Favorites.CELLX);
+        final int indexCellY = c.getColumnIndexOrThrow(Favorites.CELLY);
+        final int indexSpanX = c.getColumnIndexOrThrow(Favorites.SPANX);
+        final int indexSpanY = c.getColumnIndexOrThrow(Favorites.SPANY);
+        final int indexIntent = c.getColumnIndexOrThrow(Favorites.INTENT);
+        final int indexAppWidgetProvider = c.getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
+        final int indexAppWidgetId = c.getColumnIndexOrThrow(Favorites.APPWIDGET_ID);
+
+        ArrayList<DbEntry> entries = new ArrayList<>();
+        while (c.moveToNext()) {
+            DbEntry entry = new DbEntry();
+            entry.id = c.getLong(indexId);
+            entry.itemType = c.getInt(indexItemType);
+            entry.cellX = c.getInt(indexCellX);
+            entry.cellY = c.getInt(indexCellY);
+            entry.spanX = c.getInt(indexSpanX);
+            entry.spanY = c.getInt(indexSpanY);
+            entry.screenId = screen;
+
+            try {
+                // calculate weight
+                switch (entry.itemType) {
+                    case Favorites.ITEM_TYPE_SHORTCUT:
+                    case Favorites.ITEM_TYPE_APPLICATION: {
+                        verifyIntent(c.getString(indexIntent));
+                        entry.weight = entry.itemType == Favorites.ITEM_TYPE_SHORTCUT
+                            ? WT_SHORTCUT : WT_APPLICATION;
+                        break;
+                    }
+                    case Favorites.ITEM_TYPE_APPWIDGET: {
+                        String provider = c.getString(indexAppWidgetProvider);
+                        ComponentName cn = ComponentName.unflattenFromString(provider);
+                        verifyPackage(cn.getPackageName());
+                        entry.weight = Math.max(WT_WIDGET_MIN, WT_WIDGET_FACTOR
+                                * entry.spanX * entry.spanY);
+
+                        int widgetId = c.getInt(indexAppWidgetId);
+                        LauncherAppWidgetProviderInfo pInfo = AppWidgetManagerCompat.getInstance(
+                                mContext).getLauncherAppWidgetInfo(widgetId);
+                        Point spans = pInfo == null ?
+                                mWidgetMinSize.get(provider) : pInfo.getMinSpans(mIdp, mContext);
+                        if (spans != null) {
+                            entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
+                            entry.minSpanY = spans.y > 0 ? spans.y : entry.spanY;
+                        } else {
+                            // Assume that the widget be resized down to 2x2
+                            entry.minSpanX = entry.minSpanY = 2;
+                        }
+
+                        if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
+                            throw new Exception("Widget can't be resized down to fit the grid");
+                        }
+                        break;
+                    }
+                    case Favorites.ITEM_TYPE_FOLDER: {
+                        int total = getFolderItemsCount(entry.id);
+                        if (total == 0) {
+                            throw new Exception("Folder is empty");
+                        }
+                        entry.weight = WT_FOLDER_FACTOR * total;
+                        break;
+                    }
+                    default:
+                        throw new Exception("Invalid item type");
+                }
+            } catch (Exception e) {
+                if (DEBUG) {
+                    Log.d(TAG, "Removing item " + entry.id, e);
+                }
+                mEntryToRemove.add(entry.id);
+                continue;
+            }
+            entries.add(entry);
+        }
+        c.close();
+        return entries;
+    }
+
+    /**
+     * @return the number of valid items in the folder.
+     */
+    private int getFolderItemsCount(long folderId) {
+        Cursor c =  mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[]{Favorites._ID, Favorites.INTENT},
+                Favorites.CONTAINER + " = " + folderId, null, null, null);
+
+        int total = 0;
+        while (c.moveToNext()) {
+            try {
+                verifyIntent(c.getString(1));
+                total++;
+            } catch (Exception e) {
+                mEntryToRemove.add(c.getLong(0));
+            }
+        }
+        c.close();
+        return total;
+    }
+
+    /**
+     * Verifies if the intent should be restored.
+     */
+    private void verifyIntent(String intentStr) throws Exception {
+        Intent intent = Intent.parseUri(intentStr, 0);
+        if (intent.getComponent() != null) {
+            verifyPackage(intent.getComponent().getPackageName());
+        } else if (intent.getPackage() != null) {
+            // Only verify package if the component was null.
+            verifyPackage(intent.getPackage());
+        }
+    }
+
+    /**
+     * Verifies if the package should be restored
+     */
+    private void verifyPackage(String packageName) throws Exception {
+        if (!mValidPackages.contains(packageName)) {
+            throw new Exception("Package not available");
+        }
+    }
+
+    private static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
+
+        public float weight;
+
+        public DbEntry() { }
+
+        public DbEntry copy() {
+            DbEntry entry = new DbEntry();
+            entry.copyFrom(this);
+            entry.weight = weight;
+            entry.minSpanX = minSpanX;
+            entry.minSpanY = minSpanY;
+            return entry;
+        }
+
+        /**
+         * Comparator such that larger widgets come first,  followed by all 1x1 items
+         * based on their weights.
+         */
+        @Override
+        public int compareTo(DbEntry another) {
+            if (itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+                if (another.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+                    return another.spanY * another.spanX - spanX * spanY;
+                } else {
+                    return -1;
+                }
+            } else if (another.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+                return 1;
+            } else {
+                // Place higher weight before lower weight.
+                return Float.compare(another.weight, weight);
+            }
+        }
+
+        public boolean columnsSame(DbEntry org) {
+            return org.cellX == cellX && org.cellY == cellY && org.spanX == spanX &&
+                    org.spanY == spanY && org.screenId == screenId;
+        }
+
+        public void addToContentValues(ContentValues values) {
+            values.put(LauncherSettings.Favorites.SCREEN, screenId);
+            values.put(LauncherSettings.Favorites.CELLX, cellX);
+            values.put(LauncherSettings.Favorites.CELLY, cellY);
+            values.put(LauncherSettings.Favorites.SPANX, spanX);
+            values.put(LauncherSettings.Favorites.SPANY, spanY);
+        }
+    }
+
+    private static ArrayList<DbEntry> deepCopy(ArrayList<DbEntry> src) {
+        ArrayList<DbEntry> dup = new ArrayList<DbEntry>(src.size());
+        for (DbEntry e : src) {
+            dup.add(e.copy());
+        }
+        return dup;
+    }
+
+    private static Point parsePoint(String point) {
+        String[] split = point.split(",");
+        return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
+    }
+
+    private static String getPointString(int x, int y) {
+        return String.format(Locale.ENGLISH, "%d,%d", x, y);
+    }
+
+    public static void markForMigration(
+            Context context, HashSet<String> widgets, BackupProtos.DeviceProfieData srcProfile) {
+        Utilities.getPrefs(context).edit()
+                .putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE,
+                        getPointString((int) srcProfile.desktopCols, (int) srcProfile.desktopRows))
+                .putString(KEY_MIGRATION_SRC_HOTSEAT_SIZE,
+                        getPointString((int) srcProfile.hotseatCount, srcProfile.allappsRank))
+                .putStringSet(KEY_MIGRATION_WIDGET_MINSIZE, widgets)
+                .apply();
+    }
+
+    /**
+     * Migrates the workspace and hotseat in case their sizes changed.
+     * @return false if the migration failed.
+     */
+    public static boolean migrateGridIfNeeded(Context context) {
+        SharedPreferences prefs = Utilities.getPrefs(context);
+        InvariantDeviceProfile idp = LauncherAppState.getInstance().getInvariantDeviceProfile();
+
+        String gridSizeString = getPointString(idp.numColumns, idp.numRows);
+        String hotseatSizeString = getPointString(idp.numHotseatIcons, idp.hotseatAllAppsRank);
+
+        if (gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, "")) &&
+                hotseatSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_HOTSEAT_SIZE, ""))) {
+            // Skip if workspace and hotseat sizes have not changed.
+            return true;
+        }
+
+        long migrationStartTime = System.currentTimeMillis();
+        try {
+            boolean dbChanged = false;
+
+            // Initialize list of valid packages. This contain all the packages which are already on
+            // the device and packages which are being installed. Any item which doesn't belong to
+            // this set is removed.
+            // Since the loader removes such items anyway, removing these items here doesn't cause
+            // any extra data loss and gives us more free space on the grid for better migration.
+            HashSet validPackages = new HashSet<>();
+            for (PackageInfo info : context.getPackageManager().getInstalledPackages(0)) {
+                validPackages.add(info.packageName);
+            }
+            validPackages.addAll(PackageInstallerCompat.getInstance(context)
+                    .updateAndGetActiveSessionCache().keySet());
+
+            // Hotseat
+            Point srcHotseatSize = parsePoint(prefs.getString(
+                    KEY_MIGRATION_SRC_HOTSEAT_SIZE, hotseatSizeString));
+            if (srcHotseatSize.x != idp.numHotseatIcons ||
+                    srcHotseatSize.y != idp.hotseatAllAppsRank) {
+                // Migrate hotseat.
+
+                dbChanged = new GridSizeMigrationTask(context,
+                        LauncherAppState.getInstance().getInvariantDeviceProfile(),
+                        validPackages,
+                        srcHotseatSize.x, srcHotseatSize.y,
+                        idp.numHotseatIcons, idp.hotseatAllAppsRank).migrateHotseat();
+            }
+
+            // Grid size
+            Point targetSize = new Point(idp.numColumns, idp.numRows);
+            Point sourceSize = parsePoint(prefs.getString(
+                    KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString));
+
+            if (!targetSize.equals(sourceSize)) {
+
+                // The following list defines all possible grid sizes (and intermediate steps
+                // during migration). Note that at each step, dx <= 1 && dy <= 1. Any grid size
+                // which is not in this list is not migrated.
+                // Note that the InvariantDeviceProfile defines (rows, cols) but the Points
+                // specified here are defined as (cols, rows).
+                ArrayList<Point> gridSizeSteps = new ArrayList<>();
+                gridSizeSteps.add(new Point(3, 2));
+                gridSizeSteps.add(new Point(3, 3));
+                gridSizeSteps.add(new Point(4, 3));
+                gridSizeSteps.add(new Point(4, 4));
+                gridSizeSteps.add(new Point(5, 5));
+                gridSizeSteps.add(new Point(6, 5));
+                gridSizeSteps.add(new Point(6, 6));
+                gridSizeSteps.add(new Point(7, 7));
+
+                int sourceSizeIndex = gridSizeSteps.indexOf(sourceSize);
+                int targetSizeIndex = gridSizeSteps.indexOf(targetSize);
+
+                if (sourceSizeIndex <= -1 || targetSizeIndex <= -1) {
+                    throw new Exception("Unable to migrate grid size from " + sourceSize
+                            + " to " + targetSize);
+                }
+
+                // Min widget sizes
+                HashMap<String, Point> widgetMinSize = new HashMap<>();
+                for (String s : Utilities.getPrefs(context).getStringSet(KEY_MIGRATION_WIDGET_MINSIZE,
+                        Collections.<String>emptySet())) {
+                    String[] parts = s.split("#");
+                    widgetMinSize.put(parts[0], parsePoint(parts[1]));
+                }
+
+                // Migrate the workspace grid, step by step.
+                while (targetSizeIndex < sourceSizeIndex ) {
+                    // We only need to migrate the grid if source size is greater
+                    // than the target size.
+                    Point stepTargetSize = gridSizeSteps.get(sourceSizeIndex - 1);
+                    Point stepSourceSize = gridSizeSteps.get(sourceSizeIndex);
+
+                    if (new GridSizeMigrationTask(context,
+                            LauncherAppState.getInstance().getInvariantDeviceProfile(),
+                            validPackages, widgetMinSize,
+                            stepSourceSize, stepTargetSize).migrateWorkspace()) {
+                        dbChanged = true;
+                    }
+                    sourceSizeIndex--;
+                }
+            }
+
+            if (dbChanged) {
+                // Make sure we haven't removed everything.
+                final Cursor c = context.getContentResolver().query(
+                        LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
+                boolean hasData = c.moveToNext();
+                c.close();
+                if (!hasData) {
+                    throw new Exception("Removed every thing during grid resize");
+                }
+            }
+
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, "Error during grid migration", e);
+
+            return false;
+        } finally {
+            Log.v(TAG, "Workspace migration completed in "
+                    + (System.currentTimeMillis() - migrationStartTime));
+
+            // Save current configuration, so that the migration does not run again.
+            prefs.edit()
+                    .putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString)
+                    .putString(KEY_MIGRATION_SRC_HOTSEAT_SIZE, hotseatSizeString)
+                    .remove(KEY_MIGRATION_WIDGET_MINSIZE)
+                    .apply();
+        }
+    }
+}
diff --git a/src/com/android/launcher3/model/MigrateFromRestoreTask.java b/src/com/android/launcher3/model/MigrateFromRestoreTask.java
deleted file mode 100644
index 786ab60..0000000
--- a/src/com/android/launcher3/model/MigrateFromRestoreTask.java
+++ /dev/null
@@ -1,763 +0,0 @@
-package com.android.launcher3.model;
-
-import android.content.ComponentName;
-import android.content.ContentProviderOperation;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.database.Cursor;
-import android.graphics.Point;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.compat.PackageInstallerCompat;
-import com.android.launcher3.compat.UserHandleCompat;
-import com.android.launcher3.util.LongArrayMap;
-import com.android.launcher3.util.Thunk;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-
-/**
- * This class takes care of shrinking the workspace (by maximum of one row and one column), as a
- * result of restoring from a larger device.
- */
-public class MigrateFromRestoreTask {
-
-    public static boolean ENABLED = false;
-
-    private static final String TAG = "MigrateFromRestoreTask";
-    private static final boolean DEBUG = true;
-
-    private static final String KEY_MIGRATION_SOURCE_SIZE = "migration_restore_src_size";
-    private static final String KEY_MIGRATION_WIDGET_MINSIZE = "migration_widget_min_size";
-
-    // These are carefully selected weights for various item types (Math.random?), to allow for
-    // the lease absurd migration experience.
-    private static final float WT_SHORTCUT = 1;
-    private static final float WT_APPLICATION = 0.8f;
-    private static final float WT_WIDGET_MIN = 2;
-    private static final float WT_WIDGET_FACTOR = 0.6f;
-    private static final float WT_FOLDER_FACTOR = 0.5f;
-
-    private final Context mContext;
-    private final ContentValues mTempValues = new ContentValues();
-    private final HashMap<String, Point> mWidgetMinSize;
-    private final InvariantDeviceProfile mIdp;
-
-    private HashSet<String> mValidPackages;
-    public ArrayList<Long> mEntryToRemove;
-    private ArrayList<ContentProviderOperation> mUpdateOperations;
-
-    private ArrayList<DbEntry> mCarryOver;
-
-    private final int mSrcX, mSrcY;
-    @Thunk final int mTrgX, mTrgY;
-    private final boolean mShouldRemoveX, mShouldRemoveY;
-
-    public MigrateFromRestoreTask(Context context) {
-        mContext = context;
-
-        SharedPreferences prefs = Utilities.getPrefs(context);
-        Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SOURCE_SIZE, ""));
-        mSrcX = sourceSize.x;
-        mSrcY = sourceSize.y;
-
-        mWidgetMinSize = new HashMap<String, Point>();
-        for (String s : prefs.getStringSet(KEY_MIGRATION_WIDGET_MINSIZE,
-                Collections.<String>emptySet())) {
-            String[] parts = s.split("#");
-            mWidgetMinSize.put(parts[0], parsePoint(parts[1]));
-        }
-
-        mIdp = LauncherAppState.getInstance().getInvariantDeviceProfile();
-        mTrgX = mIdp.numColumns;
-        mTrgY = mIdp.numRows;
-        mShouldRemoveX = mTrgX < mSrcX;
-        mShouldRemoveY = mTrgY < mSrcY;
-    }
-
-    public void execute() throws Exception {
-        mEntryToRemove = new ArrayList<>();
-        mCarryOver = new ArrayList<>();
-        mUpdateOperations = new ArrayList<>();
-
-        // Initialize list of valid packages. This contain all the packages which are already on
-        // the device and packages which are being installed. Any item which doesn't belong to
-        // this set is removed.
-        // Since the loader removes such items anyway, removing these items here doesn't cause any
-        // extra data loss and gives us more free space on the grid for better migration.
-        mValidPackages = new HashSet<>();
-        for (PackageInfo info : mContext.getPackageManager().getInstalledPackages(0)) {
-            mValidPackages.add(info.packageName);
-        }
-        mValidPackages.addAll(PackageInstallerCompat.getInstance(mContext)
-                .updateAndGetActiveSessionCache().keySet());
-
-        ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(mContext);
-        if (allScreens.isEmpty()) {
-            throw new Exception("Unable to get workspace screens");
-        }
-
-        for (long screenId : allScreens) {
-            if (DEBUG) {
-                Log.d(TAG, "Migrating " + screenId);
-            }
-            migrateScreen(screenId);
-        }
-
-        if (!mCarryOver.isEmpty()) {
-            LongArrayMap<DbEntry> itemMap = new LongArrayMap<>();
-            for (DbEntry e : mCarryOver) {
-                itemMap.put(e.id, e);
-            }
-
-            do {
-                // Some items are still remaining. Try adding a few new screens.
-
-                // At every iteration, make sure that at least one item is removed from
-                // {@link #mCarryOver}, to prevent an infinite loop. If no item could be removed,
-                // break the loop and abort migration by throwing an exception.
-                OptimalPlacementSolution placement = new OptimalPlacementSolution(
-                        new boolean[mTrgX][mTrgY], deepCopy(mCarryOver), true);
-                placement.find();
-                if (placement.finalPlacedItems.size() > 0) {
-                    long newScreenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
-                    allScreens.add(newScreenId);
-                    for (DbEntry item : placement.finalPlacedItems) {
-                        if (!mCarryOver.remove(itemMap.get(item.id))) {
-                            throw new Exception("Unable to find matching items");
-                        }
-                        item.screenId = newScreenId;
-                        update(item);
-                    }
-                } else {
-                    throw new Exception("None of the items can be placed on an empty screen");
-                }
-
-            } while (!mCarryOver.isEmpty());
-
-
-            LauncherAppState.getInstance().getModel()
-                .updateWorkspaceScreenOrder(mContext, allScreens);
-        }
-
-        // Update items
-        mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, mUpdateOperations);
-
-        if (!mEntryToRemove.isEmpty()) {
-            if (DEBUG) {
-                Log.d(TAG, "Removing items: " + TextUtils.join(", ", mEntryToRemove));
-            }
-            mContext.getContentResolver().delete(LauncherSettings.Favorites.CONTENT_URI,
-                    Utilities.createDbSelectionQuery(
-                            LauncherSettings.Favorites._ID, mEntryToRemove), null);
-        }
-
-        // Make sure we haven't removed everything.
-        final Cursor c = mContext.getContentResolver().query(
-                LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
-        boolean hasData = c.moveToNext();
-        c.close();
-        if (!hasData) {
-            throw new Exception("Removed every thing during grid resize");
-        }
-    }
-
-    /**
-     * Migrate a particular screen id.
-     * Strategy:
-     *   1) For all possible combinations of row and column, pick the one which causes the least
-     *      data loss: {@link #tryRemove(int, int, ArrayList, float[])}
-     *   2) Maintain a list of all lost items before this screen, and add any new item lost from
-     *      this screen to that list as well.
-     *   3) If all those items from the above list can be placed on this screen, place them
-     *      (otherwise they are placed on a new screen).
-     */
-    private void migrateScreen(long screenId) {
-        ArrayList<DbEntry> items = loadEntries(screenId);
-
-        int removedCol = Integer.MAX_VALUE;
-        int removedRow = Integer.MAX_VALUE;
-
-        // removeWt represents the cost function for loss of items during migration, and moveWt
-        // represents the cost function for repositioning the items. moveWt is only considered if
-        // removeWt is same for two different configurations.
-        // Start with Float.MAX_VALUE (assuming full data) and pick the configuration with least
-        // cost.
-        float removeWt = Float.MAX_VALUE;
-        float moveWt = Float.MAX_VALUE;
-        float[] outLoss = new float[2];
-        ArrayList<DbEntry> finalItems = null;
-
-        // Try removing all possible combinations
-        for (int x = 0; x < mSrcX; x++) {
-            for (int y = 0; y < mSrcY; y++) {
-                // Use a deep copy when trying out a particular combination as it can change
-                // the underlying object.
-                ArrayList<DbEntry> itemsOnScreen = tryRemove(x, y, deepCopy(items), outLoss);
-
-                if ((outLoss[0] < removeWt) || ((outLoss[0] == removeWt) && (outLoss[1] < moveWt))) {
-                    removeWt = outLoss[0];
-                    moveWt = outLoss[1];
-                    removedCol = mShouldRemoveX ? x : removedCol;
-                    removedRow = mShouldRemoveY ? y : removedRow;
-                    finalItems = itemsOnScreen;
-                }
-
-                // No need to loop over all rows, if a row removal is not needed.
-                if (!mShouldRemoveY) {
-                    break;
-                }
-            }
-
-            if (!mShouldRemoveX) {
-                break;
-            }
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, String.format("Removing row %d, column %d on screen %d",
-                    removedRow, removedCol, screenId));
-        }
-
-        LongArrayMap<DbEntry> itemMap = new LongArrayMap<>();
-        for (DbEntry e : deepCopy(items)) {
-            itemMap.put(e.id, e);
-        }
-
-        for (DbEntry item : finalItems) {
-            DbEntry org = itemMap.get(item.id);
-            itemMap.remove(item.id);
-
-            // Check if update is required
-            if (!item.columnsSame(org)) {
-                update(item);
-            }
-        }
-
-        // The remaining items in {@link #itemMap} are those which didn't get placed.
-        for (DbEntry item : itemMap) {
-            mCarryOver.add(item);
-        }
-
-        if (!mCarryOver.isEmpty() && removeWt == 0) {
-            // No new items were removed in this step. Try placing all the items on this screen.
-            boolean[][] occupied = new boolean[mTrgX][mTrgY];
-            for (DbEntry item : finalItems) {
-                markCells(occupied, item, true);
-            }
-
-            OptimalPlacementSolution placement = new OptimalPlacementSolution(occupied,
-                    deepCopy(mCarryOver), true);
-            placement.find();
-            if (placement.lowestWeightLoss == 0) {
-                // All items got placed
-
-                for (DbEntry item : placement.finalPlacedItems) {
-                    item.screenId = screenId;
-                    update(item);
-                }
-
-                mCarryOver.clear();
-            }
-        }
-    }
-
-    /**
-     * Updates an item in the DB.
-     */
-    private void update(DbEntry item) {
-        mTempValues.clear();
-        item.addToContentValues(mTempValues);
-        mUpdateOperations.add(ContentProviderOperation
-                .newUpdate(LauncherSettings.Favorites.getContentUri(item.id))
-                .withValues(mTempValues).build());
-    }
-
-    /**
-     * Tries the remove the provided row and column.
-     * @param items all the items on the screen under operation
-     * @param outLoss array of size 2. The first entry is filled with weight loss, and the second
-     * with the overall item movement.
-     */
-    private ArrayList<DbEntry> tryRemove(int col, int row, ArrayList<DbEntry> items,
-            float[] outLoss) {
-        boolean[][] occupied = new boolean[mTrgX][mTrgY];
-
-        col = mShouldRemoveX ? col : Integer.MAX_VALUE;
-        row = mShouldRemoveY ? row : Integer.MAX_VALUE;
-
-        ArrayList<DbEntry> finalItems = new ArrayList<>();
-        ArrayList<DbEntry> removedItems = new ArrayList<>();
-
-        for (DbEntry item : items) {
-            if ((item.cellX <= col && (item.spanX + item.cellX) > col)
-                || (item.cellY <= row && (item.spanY + item.cellY) > row)) {
-                removedItems.add(item);
-                if (item.cellX >= col) item.cellX --;
-                if (item.cellY >= row) item.cellY --;
-            } else {
-                if (item.cellX > col) item.cellX --;
-                if (item.cellY > row) item.cellY --;
-                finalItems.add(item);
-                markCells(occupied, item, true);
-            }
-        }
-
-        OptimalPlacementSolution placement = new OptimalPlacementSolution(occupied, removedItems);
-        placement.find();
-        finalItems.addAll(placement.finalPlacedItems);
-        outLoss[0] = placement.lowestWeightLoss;
-        outLoss[1] = placement.lowestMoveCost;
-        return finalItems;
-    }
-
-    @Thunk void markCells(boolean[][] occupied, DbEntry item, boolean val) {
-        for (int i = item.cellX; i < (item.cellX + item.spanX); i++) {
-            for (int j = item.cellY; j < (item.cellY + item.spanY); j++) {
-                occupied[i][j] = val;
-            }
-        }
-    }
-
-    @Thunk boolean isVacant(boolean[][] occupied, int x, int y, int w, int h) {
-        if (x + w > mTrgX) return false;
-        if (y + h > mTrgY) return false;
-
-        for (int i = 0; i < w; i++) {
-            for (int j = 0; j < h; j++) {
-                if (occupied[i + x][j + y]) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private class OptimalPlacementSolution {
-        private final ArrayList<DbEntry> itemsToPlace;
-        private final boolean[][] occupied;
-
-        // If set to true, item movement are not considered in move cost, leading to a more
-        // linear placement.
-        private final boolean ignoreMove;
-
-        float lowestWeightLoss = Float.MAX_VALUE;
-        float lowestMoveCost = Float.MAX_VALUE;
-        ArrayList<DbEntry> finalPlacedItems;
-
-        public OptimalPlacementSolution(boolean[][] occupied, ArrayList<DbEntry> itemsToPlace) {
-            this(occupied, itemsToPlace, false);
-        }
-
-        public OptimalPlacementSolution(boolean[][] occupied, ArrayList<DbEntry> itemsToPlace,
-                boolean ignoreMove) {
-            this.occupied = occupied;
-            this.itemsToPlace = itemsToPlace;
-            this.ignoreMove = ignoreMove;
-
-            // Sort the items such that larger widgets appear first followed by 1x1 items
-            Collections.sort(this.itemsToPlace);
-        }
-
-        public void find() {
-            find(0, 0, 0, new ArrayList<DbEntry>());
-        }
-
-        /**
-         * Recursively finds a placement for the provided items.
-         * @param index the position in {@link #itemsToPlace} to start looking at.
-         * @param weightLoss total weight loss upto this point
-         * @param moveCost total move cost upto this point
-         * @param itemsPlaced all the items already placed upto this point
-         */
-        public void find(int index, float weightLoss, float moveCost,
-                ArrayList<DbEntry> itemsPlaced) {
-            if ((weightLoss >= lowestWeightLoss) ||
-                    ((weightLoss == lowestWeightLoss) && (moveCost >= lowestMoveCost))) {
-                // Abort, as we already have a better solution.
-                return;
-
-            } else if (index >= itemsToPlace.size()) {
-                // End loop.
-                lowestWeightLoss = weightLoss;
-                lowestMoveCost = moveCost;
-
-                // Keep a deep copy of current configuration as it can change during recursion.
-                finalPlacedItems = deepCopy(itemsPlaced);
-                return;
-            }
-
-            DbEntry me = itemsToPlace.get(index);
-            int myX = me.cellX;
-            int myY = me.cellY;
-
-            // List of items to pass over if this item was placed.
-            ArrayList<DbEntry> itemsIncludingMe = new ArrayList<>(itemsPlaced.size() + 1);
-            itemsIncludingMe.addAll(itemsPlaced);
-            itemsIncludingMe.add(me);
-
-            if (me.spanX > 1 || me.spanY > 1) {
-                // If the current item is a widget (and it greater than 1x1), try to place it at
-                // all possible positions. This is because a widget placed at one position can
-                // affect the placement of a different widget.
-                int myW = me.spanX;
-                int myH = me.spanY;
-
-                for (int y = 0; y < mTrgY; y++) {
-                    for (int x = 0; x < mTrgX; x++) {
-                        float newMoveCost = moveCost;
-                        if (x != myX) {
-                            me.cellX = x;
-                            newMoveCost ++;
-                        }
-                        if (y != myY) {
-                            me.cellY = y;
-                            newMoveCost ++;
-                        }
-                        if (ignoreMove) {
-                            newMoveCost = moveCost;
-                        }
-
-                        if (isVacant(occupied, x, y, myW, myH)) {
-                            // place at this position and continue search.
-                            markCells(occupied, me, true);
-                            find(index + 1, weightLoss, newMoveCost, itemsIncludingMe);
-                            markCells(occupied, me, false);
-                        }
-
-                        // Try resizing horizontally
-                        if (myW > me.minSpanX && isVacant(occupied, x, y, myW - 1, myH)) {
-                            me.spanX --;
-                            markCells(occupied, me, true);
-                            // 1 extra move cost
-                            find(index + 1, weightLoss, newMoveCost + 1, itemsIncludingMe);
-                            markCells(occupied, me, false);
-                            me.spanX ++;
-                        }
-
-                        // Try resizing vertically
-                        if (myH > me.minSpanY && isVacant(occupied, x, y, myW, myH - 1)) {
-                            me.spanY --;
-                            markCells(occupied, me, true);
-                            // 1 extra move cost
-                            find(index + 1, weightLoss, newMoveCost + 1, itemsIncludingMe);
-                            markCells(occupied, me, false);
-                            me.spanY ++;
-                        }
-
-                        // Try resizing horizontally & vertically
-                        if (myH > me.minSpanY && myW > me.minSpanX &&
-                                isVacant(occupied, x, y, myW - 1, myH - 1)) {
-                            me.spanX --;
-                            me.spanY --;
-                            markCells(occupied, me, true);
-                            // 2 extra move cost
-                            find(index + 1, weightLoss, newMoveCost + 2, itemsIncludingMe);
-                            markCells(occupied, me, false);
-                            me.spanX ++;
-                            me.spanY ++;
-                        }
-                        me.cellX = myX;
-                        me.cellY = myY;
-                    }
-                }
-
-                // Finally also try a solution when this item is not included. Trying it in the end
-                // causes it to get skipped in most cases due to higher weight loss, and prevents
-                // unnecessary deep copies of various configurations.
-                find(index + 1, weightLoss + me.weight, moveCost, itemsPlaced);
-            } else {
-                // Since this is a 1x1 item and all the following items are also 1x1, just place
-                // it at 'the most appropriate position' and hope for the best.
-                // The most appropriate position: one with lease straight line distance
-                int newDistance = Integer.MAX_VALUE;
-                int newX = Integer.MAX_VALUE, newY = Integer.MAX_VALUE;
-
-                for (int y = 0; y < mTrgY; y++) {
-                    for (int x = 0; x < mTrgX; x++) {
-                        if (!occupied[x][y]) {
-                            int dist = ignoreMove ? 0 :
-                                ((me.cellX - x) * (me.cellX - x) + (me.cellY - y) * (me.cellY - y));
-                            if (dist < newDistance) {
-                                newX = x;
-                                newY = y;
-                                newDistance = dist;
-                            }
-                        }
-                    }
-                }
-
-                if (newX < mTrgX && newY < mTrgY) {
-                    float newMoveCost = moveCost;
-                    if (newX != myX) {
-                        me.cellX = newX;
-                        newMoveCost ++;
-                    }
-                    if (newY != myY) {
-                        me.cellY = newY;
-                        newMoveCost ++;
-                    }
-                    if (ignoreMove) {
-                        newMoveCost = moveCost;
-                    }
-                    markCells(occupied, me, true);
-                    find(index + 1, weightLoss, newMoveCost, itemsIncludingMe);
-                    markCells(occupied, me, false);
-                    me.cellX = myX;
-                    me.cellY = myY;
-
-                    // Try to find a solution without this item, only if
-                    //  1) there was at least one space, i.e., we were able to place this item
-                    //  2) if the next item has the same weight (all items are already sorted), as
-                    //     if it has lower weight, that solution will automatically get discarded.
-                    //  3) ignoreMove false otherwise, move cost is ignored and the weight will
-                    //      anyway be same.
-                    if (index + 1 < itemsToPlace.size()
-                            && itemsToPlace.get(index + 1).weight >= me.weight && !ignoreMove) {
-                        find(index + 1, weightLoss + me.weight, moveCost, itemsPlaced);
-                    }
-                } else {
-                    // No more space. Jump to the end.
-                    for (int i = index + 1; i < itemsToPlace.size(); i++) {
-                        weightLoss += itemsToPlace.get(i).weight;
-                    }
-                    find(itemsToPlace.size(), weightLoss + me.weight, moveCost, itemsPlaced);
-                }
-            }
-        }
-    }
-
-    /**
-     * Loads entries for a particular screen id.
-     */
-    public ArrayList<DbEntry> loadEntries(long screen) {
-       Cursor c =  mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
-                new String[] {
-                    Favorites._ID,                  // 0
-                    Favorites.ITEM_TYPE,            // 1
-                    Favorites.CELLX,                // 2
-                    Favorites.CELLY,                // 3
-                    Favorites.SPANX,                // 4
-                    Favorites.SPANY,                // 5
-                    Favorites.INTENT,               // 6
-                    Favorites.APPWIDGET_PROVIDER},  // 7
-                Favorites.CONTAINER + " = " + Favorites.CONTAINER_DESKTOP
-                    + " AND " + Favorites.SCREEN + " = " + screen, null, null, null);
-
-       final int indexId = c.getColumnIndexOrThrow(Favorites._ID);
-       final int indexItemType = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
-       final int indexCellX = c.getColumnIndexOrThrow(Favorites.CELLX);
-       final int indexCellY = c.getColumnIndexOrThrow(Favorites.CELLY);
-       final int indexSpanX = c.getColumnIndexOrThrow(Favorites.SPANX);
-       final int indexSpanY = c.getColumnIndexOrThrow(Favorites.SPANY);
-       final int indexIntent = c.getColumnIndexOrThrow(Favorites.INTENT);
-       final int indexAppWidgetProvider = c.getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
-
-       ArrayList<DbEntry> entries = new ArrayList<>();
-       while (c.moveToNext()) {
-           DbEntry entry = new DbEntry();
-           entry.id = c.getLong(indexId);
-           entry.itemType = c.getInt(indexItemType);
-           entry.cellX = c.getInt(indexCellX);
-           entry.cellY = c.getInt(indexCellY);
-           entry.spanX = c.getInt(indexSpanX);
-           entry.spanY = c.getInt(indexSpanY);
-           entry.screenId = screen;
-
-           try {
-               // calculate weight
-               switch (entry.itemType) {
-                   case Favorites.ITEM_TYPE_SHORTCUT:
-                   case Favorites.ITEM_TYPE_APPLICATION: {
-                       verifyIntent(c.getString(indexIntent));
-                       entry.weight = entry.itemType == Favorites.ITEM_TYPE_SHORTCUT
-                           ? WT_SHORTCUT : WT_APPLICATION;
-                       break;
-                   }
-                   case Favorites.ITEM_TYPE_APPWIDGET: {
-                       String provider = c.getString(indexAppWidgetProvider);
-                       ComponentName cn = ComponentName.unflattenFromString(provider);
-                       verifyPackage(cn.getPackageName());
-                       entry.weight = Math.max(WT_WIDGET_MIN, WT_WIDGET_FACTOR
-                               * entry.spanX * entry.spanY);
-
-                       // Migration happens for current user only.
-                       LauncherAppWidgetProviderInfo pInfo = LauncherModel.getProviderInfo(
-                               mContext, cn, UserHandleCompat.myUserHandle());
-                       Point spans = pInfo == null ?
-                               mWidgetMinSize.get(provider) : pInfo.getMinSpans(mIdp, mContext);
-                       if (spans != null) {
-                           entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
-                           entry.minSpanY = spans.y > 0 ? spans.y : entry.spanY;
-                       } else {
-                           // Assume that the widget be resized down to 2x2
-                           entry.minSpanX = entry.minSpanY = 2;
-                       }
-
-                       if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
-                           throw new Exception("Widget can't be resized down to fit the grid");
-                       }
-                       break;
-                   }
-                   case Favorites.ITEM_TYPE_FOLDER: {
-                       int total = getFolderItemsCount(entry.id);
-                       if (total == 0) {
-                           throw new Exception("Folder is empty");
-                       }
-                       entry.weight = WT_FOLDER_FACTOR * total;
-                       break;
-                   }
-                   default:
-                       throw new Exception("Invalid item type");
-               }
-           } catch (Exception e) {
-               if (DEBUG) {
-                   Log.d(TAG, "Removing item " + entry.id, e);
-               }
-               mEntryToRemove.add(entry.id);
-               continue;
-           }
-           entries.add(entry);
-       }
-       c.close();
-       return entries;
-    }
-
-    /**
-     * @return the number of valid items in the folder.
-     */
-    private int getFolderItemsCount(long folderId) {
-        Cursor c =  mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
-                new String[] {Favorites._ID, Favorites.INTENT},
-                Favorites.CONTAINER + " = " + folderId, null, null, null);
-
-        int total = 0;
-        while (c.moveToNext()) {
-            try {
-                verifyIntent(c.getString(1));
-                total++;
-            } catch (Exception e) {
-                mEntryToRemove.add(c.getLong(0));
-            }
-        }
-        c.close();
-        return total;
-    }
-
-    /**
-     * Verifies if the intent should be restored.
-     */
-    private void verifyIntent(String intentStr) throws Exception {
-        Intent intent = Intent.parseUri(intentStr, 0);
-        if (intent.getComponent() != null) {
-            verifyPackage(intent.getComponent().getPackageName());
-        } else if (intent.getPackage() != null) {
-            // Only verify package if the component was null.
-            verifyPackage(intent.getPackage());
-        }
-    }
-
-    /**
-     * Verifies if the package should be restored
-     */
-    private void verifyPackage(String packageName) throws Exception {
-        if (!mValidPackages.contains(packageName)) {
-            throw new Exception("Package not available");
-        }
-    }
-
-    private static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
-
-        public float weight;
-
-        public DbEntry() { }
-
-        public DbEntry copy() {
-            DbEntry entry = new DbEntry();
-            entry.copyFrom(this);
-            entry.weight = weight;
-            entry.minSpanX = minSpanX;
-            entry.minSpanY = minSpanY;
-            return entry;
-        }
-
-        /**
-         * Comparator such that larger widgets come first,  followed by all 1x1 items
-         * based on their weights.
-         */
-        @Override
-        public int compareTo(DbEntry another) {
-            if (itemType == Favorites.ITEM_TYPE_APPWIDGET) {
-                if (another.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
-                    return another.spanY * another.spanX - spanX * spanY;
-                } else {
-                    return -1;
-                }
-            } else if (another.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
-                return 1;
-            } else {
-                // Place higher weight before lower weight.
-                return Float.compare(another.weight, weight);
-            }
-        }
-
-        public boolean columnsSame(DbEntry org) {
-            return org.cellX == cellX && org.cellY == cellY && org.spanX == spanX &&
-                    org.spanY == spanY && org.screenId == screenId;
-        }
-
-        public void addToContentValues(ContentValues values) {
-            values.put(LauncherSettings.Favorites.SCREEN, screenId);
-            values.put(LauncherSettings.Favorites.CELLX, cellX);
-            values.put(LauncherSettings.Favorites.CELLY, cellY);
-            values.put(LauncherSettings.Favorites.SPANX, spanX);
-            values.put(LauncherSettings.Favorites.SPANY, spanY);
-        }
-    }
-
-    @Thunk static ArrayList<DbEntry> deepCopy(ArrayList<DbEntry> src) {
-        ArrayList<DbEntry> dup = new ArrayList<DbEntry>(src.size());
-        for (DbEntry e : src) {
-            dup.add(e.copy());
-        }
-        return dup;
-    }
-
-    private static Point parsePoint(String point) {
-        String[] split = point.split(",");
-        return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
-    }
-
-    public static void markForMigration(Context context, int srcX, int srcY,
-            HashSet<String> widgets) {
-        Utilities.getPrefs(context).edit()
-                .putString(KEY_MIGRATION_SOURCE_SIZE, srcX + "," + srcY)
-                .putStringSet(KEY_MIGRATION_WIDGET_MINSIZE, widgets)
-                .apply();
-    }
-
-    public static boolean shouldRunTask(Context context) {
-        return !TextUtils.isEmpty(Utilities.getPrefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
-    }
-
-    public static void clearFlags(Context context) {
-        Utilities.getPrefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
-                .remove(KEY_MIGRATION_WIDGET_MINSIZE).commit();
-    }
-
-}
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
index 99a53ff..53e5213 100644
--- a/src/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -1,9 +1,13 @@
 
 package com.android.launcher3.model;
 
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.os.DeadObjectException;
+import android.os.TransactionTooLargeException;
 import android.util.Log;
 
 import com.android.launcher3.AppFilter;
@@ -16,6 +20,7 @@
 import com.android.launcher3.compat.AlphabeticIndexCompat;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.config.ProviderConfig;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -95,8 +100,41 @@
         return mRawList;
     }
 
-    public void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
+    public boolean isEmpty() {
+        return mRawList.isEmpty();
+    }
+
+    public WidgetsModel updateAndClone(Context context) {
         Utilities.assertWorkerThread();
+
+        try {
+            final ArrayList<Object> widgetsAndShortcuts = new ArrayList<>();
+            // Widgets
+            for (AppWidgetProviderInfo widgetInfo :
+                    AppWidgetManagerCompat.getInstance(context).getAllProviders()) {
+                widgetsAndShortcuts.add(LauncherAppWidgetProviderInfo
+                        .fromProviderInfo(context, widgetInfo));
+            }
+            // Shortcuts
+            widgetsAndShortcuts.addAll(context.getPackageManager().queryIntentActivities(
+                    new Intent(Intent.ACTION_CREATE_SHORTCUT), 0));
+            setWidgetsAndShortcuts(widgetsAndShortcuts);
+        } catch (Exception e) {
+            if (!LauncherAppState.isDogfoodBuild() &&
+                    (e.getCause() instanceof TransactionTooLargeException ||
+                            e.getCause() instanceof DeadObjectException)) {
+                // the returned value may be incomplete and will not be refreshed until the next
+                // time Launcher starts.
+                // TODO: after figuring out a repro step, introduce a dirty bit to check when
+                // onResume is called to refresh the widget provider list.
+            } else {
+                throw e;
+            }
+        }
+        return clone();
+    }
+
+    private void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
         mRawList = rawWidgetsShortcuts;
         if (DEBUG) {
             Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index 1bb5787..475762f 100644
--- a/src/com/android/launcher3/testing/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -1,24 +1,16 @@
 package com.android.launcher3.testing;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import com.android.launcher3.AppInfo;
-import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.LauncherCallbacks;
-import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsSearchBarController;
 import com.android.launcher3.util.ComponentKey;
 
@@ -42,8 +34,6 @@
 
     public class LauncherExtensionCallbacks implements LauncherCallbacks {
 
-        LauncherExtensionOverlay mLauncherOverlay = new LauncherExtensionOverlay();
-
         @Override
         public void preOnCreate() {
         }
@@ -116,10 +106,6 @@
 
         @Override
         public boolean handleBackPressed() {
-            if (mLauncherOverlay.isOverlayPanelShowing()) {
-                mLauncherOverlay.hideOverlayPanel();
-                return true;
-            }
             return false;
         }
 
@@ -188,13 +174,8 @@
         }
 
         @Override
-        public boolean forceDisableVoiceButtonProxy() {
-            return false;
-        }
-
-        @Override
         public boolean providesSearch() {
-            return true;
+            return false;
         }
 
         @Override
@@ -208,10 +189,6 @@
             return false;
         }
 
-        @Override
-        public void startVoice() {
-        }
-
         CustomContentCallbacks mCustomContentCallbacks = new CustomContentCallbacks() {
 
             // Custom content is completely shown. {@code fromResume} indicates whether this was caused
@@ -249,7 +226,7 @@
 
         @Override
         public View getQsbBar() {
-            return mLauncherOverlay.getSearchBox();
+            return null;
         }
 
         @Override
@@ -288,11 +265,6 @@
         }
 
         @Override
-        public ComponentName getWallpaperPickerComponent() {
-            return null;
-        }
-
-        @Override
         public boolean overrideWallpaperDimensions() {
             return false;
         }
@@ -318,113 +290,16 @@
         }
 
         @Override
-        public boolean hasLauncherOverlay() {
-            return false;
-        }
-
-        @Override
-        public LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
-                LauncherOverlayCallbacks callbacks) {
-
-            mLauncherOverlay.setOverlayCallbacks(callbacks);
-            mLauncherOverlay.setOverlayContainer(container);
-
-            return mLauncherOverlay;
-        }
-
-        @Override
         public void setLauncherSearchCallback(Object callbacks) {
             // Do nothing
         }
 
-        class LauncherExtensionOverlay implements LauncherOverlay {
-            LauncherOverlayCallbacks mLauncherOverlayCallbacks;
-            ViewGroup mOverlayView;
-            View mSearchBox;
-            View mSearchOverlay;
-            boolean mShowOverlayFeedback;
-            int mProgress;
-            boolean mOverlayPanelShowing;
+        @Override
+        public void onAttachedToWindow() {
+        }
 
-            @Override
-            public void onScrollInteractionBegin() {
-                if (mLauncherOverlayCallbacks.canEnterFullImmersion()) {
-                    mShowOverlayFeedback = true;
-                    updatePanelOffset(0);
-                    mSearchOverlay.setVisibility(View.VISIBLE);
-                    mSearchOverlay.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-                }
-            }
-
-            @Override
-            public void onScrollChange(int progress, boolean rtl) {
-                mProgress = progress;
-                if (mShowOverlayFeedback) {
-                    updatePanelOffset(progress);
-                }
-            }
-
-            private void updatePanelOffset(int progress) {
-                int panelWidth = mSearchOverlay.getMeasuredWidth();
-                int offset = (int) ((progress / 100f) * panelWidth);
-                mSearchOverlay.setTranslationX(- panelWidth + offset);
-            }
-
-            @Override
-            public void onScrollInteractionEnd() {
-                if (mProgress > 25 && mLauncherOverlayCallbacks.enterFullImmersion()) {
-                    ObjectAnimator oa = LauncherAnimUtils.ofFloat(mSearchOverlay, "translationX", 0);
-                    oa.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator arg0) {
-                            mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
-                        }
-                    });
-                    oa.start();
-                    mOverlayPanelShowing = true;
-                    mShowOverlayFeedback = false;
-                }
-            }
-
-            @Override
-            public void onScrollSettled() {
-                if (mShowOverlayFeedback) {
-                    mSearchOverlay.setVisibility(View.INVISIBLE);
-                    mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
-                }
-                mShowOverlayFeedback = false;
-                mProgress = 0;
-            }
-
-            public void hideOverlayPanel() {
-                mLauncherOverlayCallbacks.exitFullImmersion();
-                mSearchOverlay.setVisibility(View.INVISIBLE);
-                mOverlayPanelShowing = false;
-            }
-
-            public boolean isOverlayPanelShowing() {
-                return mOverlayPanelShowing;
-            }
-
-            @Override
-            public void forceExitFullImmersion() {
-                hideOverlayPanel();
-            }
-
-            public void setOverlayContainer(InsettableFrameLayout container) {
-                mOverlayView = (ViewGroup) getLayoutInflater().inflate(
-                        R.layout.launcher_overlay_example, container);
-                mSearchOverlay = mOverlayView.findViewById(R.id.search_overlay);
-                mSearchBox = mOverlayView.findViewById(R.id.search_box);
-            }
-
-            public View getSearchBox() {
-                return mSearchBox;
-            }
-
-            public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks) {
-                mLauncherOverlayCallbacks = callbacks;
-            }
+        @Override
+        public void onDetachedFromWindow() {
         };
     }
 }
diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java
index c61fa88..bdb1639 100644
--- a/src/com/android/launcher3/util/ConfigMonitor.java
+++ b/src/com/android/launcher3/util/ConfigMonitor.java
@@ -23,26 +23,30 @@
 import android.content.res.Configuration;
 import android.util.Log;
 
+import com.android.launcher3.Utilities;
+
 /**
  * {@link BroadcastReceiver} which watches configuration changes and
- * restarts the process in case changes which affect the device profile.
+ * restarts the process in case changes which affect the device profile occur.
  */
 public class ConfigMonitor extends BroadcastReceiver {
 
     private final Context mContext;
     private final float mFontScale;
+    private final int mDensity;
 
     public ConfigMonitor(Context context) {
         mContext = context;
 
         Configuration config = context.getResources().getConfiguration();
         mFontScale = config.fontScale;
+        mDensity = getDensity(config);
     }
 
     @Override
     public void onReceive(Context context, Intent intent) {
         Configuration config = context.getResources().getConfiguration();
-        if (mFontScale != config.fontScale) {
+        if (mFontScale != config.fontScale || mDensity != getDensity(config)) {
             Log.d("ConfigMonitor", "Configuration changed, restarting launcher");
             mContext.unregisterReceiver(this);
             android.os.Process.killProcess(android.os.Process.myPid());
@@ -52,4 +56,8 @@
     public void register() {
         mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
     }
+
+    private static int getDensity(Configuration config) {
+        return Utilities.ATLEAST_JB_MR1 ? config.densityDpi : 0;
+    }
 }
diff --git a/src/com/android/launcher3/util/FlagOp.java b/src/com/android/launcher3/util/FlagOp.java
new file mode 100644
index 0000000..5e26ed1
--- /dev/null
+++ b/src/com/android/launcher3/util/FlagOp.java
@@ -0,0 +1,30 @@
+package com.android.launcher3.util;
+
+public abstract class FlagOp {
+
+    public static FlagOp NO_OP = new FlagOp() {};
+
+    private FlagOp() {}
+
+    public int apply(int flags) {
+        return flags;
+    }
+
+    public static FlagOp addFlag(final int flag) {
+        return new FlagOp() {
+            @Override
+            public int apply(int flags) {
+                return flags | flag;
+            }
+        };
+    }
+
+    public static FlagOp removeFlag(final int flag) {
+        return new FlagOp() {
+            @Override
+            public int apply(int flags) {
+                return flags & ~flag;
+            }
+        };
+    }
+}
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
new file mode 100644
index 0000000..08e8e86
--- /dev/null
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+
+import com.android.launcher3.Utilities;
+
+/**
+ * Utility methods using package manager
+ */
+public class PackageManagerHelper {
+
+    private static final int FLAG_SUSPENDED = 1<<30;
+
+    /**
+     * Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
+     * guarantee that the app is on SD card.
+     */
+    public static boolean isAppOnSdcard(PackageManager pm, String packageName) {
+        return isAppEnabled(pm, packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+    }
+
+    public static boolean isAppEnabled(PackageManager pm, String packageName) {
+        return isAppEnabled(pm, packageName, 0);
+    }
+
+    public static boolean isAppEnabled(PackageManager pm, String packageName, int flags) {
+        try {
+            ApplicationInfo info = pm.getApplicationInfo(packageName, flags);
+            return info != null && info.enabled;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    public static boolean isAppSuspended(PackageManager pm, String packageName) {
+        try {
+            ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+            return info != null && isAppSuspended(info);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    public static boolean isAppSuspended(ApplicationInfo info) {
+        // The value of FLAG_SUSPENDED was reused by a hidden constant
+        // ApplicationInfo.FLAG_PRIVILEGED prior to N, so only check for suspended flag on N
+        // or later.
+        if (Utilities.isNycOrAbove()) {
+            return (info.flags & FLAG_SUSPENDED) != 0;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/launcher3/util/StringFilter.java b/src/com/android/launcher3/util/StringFilter.java
new file mode 100644
index 0000000..f539ad1
--- /dev/null
+++ b/src/com/android/launcher3/util/StringFilter.java
@@ -0,0 +1,31 @@
+package com.android.launcher3.util;
+
+import java.util.Set;
+
+/**
+ * Abstract class to filter a set of strings.
+ */
+public abstract class StringFilter {
+
+    private StringFilter() { }
+
+    public abstract boolean matches(String str);
+
+    public static StringFilter matchesAll() {
+        return new StringFilter() {
+            @Override
+            public boolean matches(String str) {
+                return true;
+            }
+        };
+    }
+
+    public static StringFilter of(final Set<String> validEntries) {
+        return new StringFilter() {
+            @Override
+            public boolean matches(String str) {
+                return validEntries.contains(str);
+            }
+        };
+    }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 10a00c6..c8e8cf8 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -332,6 +332,10 @@
         mAdapter.notifyDataSetChanged();
     }
 
+    public boolean isEmpty() {
+        return mAdapter.getItemCount() == 0;
+    }
+
     private WidgetPreviewLoader getWidgetPreviewLoader() {
         if (mWidgetPreviewLoader == null) {
             mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache();
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java b/tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
new file mode 100644
index 0000000..ec157bc
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
@@ -0,0 +1,317 @@
+package com.android.launcher3.model;
+
+import android.content.ContentValues;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Point;
+import android.test.ProviderTestCase2;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.config.ProviderConfig;
+import com.android.launcher3.util.TestLauncherProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * Unit tests for {@link GridSizeMigrationTask}
+ */
+public class GridSizeMigrationTaskTest extends ProviderTestCase2<TestLauncherProvider> {
+
+    private static final long DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+    private static final long HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+
+    private static final int APPLICATION = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+    private static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+
+    private static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
+    private static final String VALID_INTENT =
+            new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0);
+
+    private HashSet<String> mValidPackages;
+    private InvariantDeviceProfile mIdp;
+
+    public GridSizeMigrationTaskTest() {
+        super(TestLauncherProvider.class, ProviderConfig.AUTHORITY);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mValidPackages = new HashSet<>();
+        mValidPackages.add(TEST_PACKAGE);
+
+        mIdp = new InvariantDeviceProfile();
+    }
+
+    public void testHotseatMigration_apps_dropped() throws Exception {
+        long[] hotseatItems = {
+                addItem(APPLICATION, 0, HOTSEAT, 0, 0),
+                addItem(SHORTCUT, 1, HOTSEAT, 0, 0),
+                -1,
+                addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
+                addItem(APPLICATION, 4, HOTSEAT, 0, 0),
+        };
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 2, 3, 1)
+                .migrateHotseat();
+        // First & last items are dropped as they have the least weight.
+        verifyHotseat(hotseatItems[1], -1, hotseatItems[3]);
+    }
+
+    public void testHotseatMigration_shortcuts_dropped() throws Exception {
+        long[] hotseatItems = {
+                addItem(APPLICATION, 0, HOTSEAT, 0, 0),
+                addItem(30, 1, HOTSEAT, 0, 0),
+                -1,
+                addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
+                addItem(10, 4, HOTSEAT, 0, 0),
+        };
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 2, 3, 1)
+                .migrateHotseat();
+        // First & third items are dropped as they have the least weight.
+        verifyHotseat(hotseatItems[1], -1, hotseatItems[4]);
+    }
+
+    private void verifyHotseat(long... sortedIds) {
+        int screenId = 0;
+        int total = 0;
+
+        for (long id : sortedIds) {
+            Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                    new String[]{LauncherSettings.Favorites._ID},
+                    "container=-101 and screen=" + screenId, null, null, null);
+
+            if (id == -1) {
+                assertEquals(0, c.getCount());
+            } else {
+                assertEquals(1, c.getCount());
+                c.moveToNext();
+                assertEquals(id, c.getLong(0));
+                total ++;
+            }
+            c.close();
+
+            screenId++;
+        }
+
+        // Verify that not other entry exist in the DB.
+        Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[]{LauncherSettings.Favorites._ID},
+                "container=-101", null, null, null);
+        assertEquals(total, c.getCount());
+        c.close();
+    }
+
+    public void testWorkspace_empty_row_column_removed() throws Exception {
+        long[][][] ids = createGrid(new int[][][]{{
+                {  0,  0, -1,  1},
+                {  3,  1, -1,  4},
+                { -1, -1, -1, -1},
+                {  5,  2, -1,  6},
+        }});
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
+                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
+
+        // Column 2 and row 2 got removed.
+        verifyWorkspace(new long[][][] {{
+                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
+                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
+                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
+        }});
+    }
+
+    public void testWorkspace_new_screen_created() throws Exception {
+        long[][][] ids = createGrid(new int[][][]{{
+                {  0,  0,  0,  1},
+                {  3,  1,  0,  4},
+                { -1, -1, -1, -1},
+                {  5,  2, -1,  6},
+        }});
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
+                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
+
+        // Items in the second column get moved to new screen
+        verifyWorkspace(new long[][][] {{
+                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
+                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
+                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
+        }, {
+                {ids[0][0][2], ids[0][1][2], -1},
+        }});
+    }
+
+    public void testWorkspace_items_merged_in_next_screen() throws Exception {
+        long[][][] ids = createGrid(new int[][][]{{
+                {  0,  0,  0,  1},
+                {  3,  1,  0,  4},
+                { -1, -1, -1, -1},
+                {  5,  2, -1,  6},
+        },{
+                {  0,  0, -1,  1},
+                {  3,  1, -1,  4},
+        }});
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
+                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
+
+        // Items in the second column of the first screen should get placed on the 3rd
+        // row of the second screen
+        verifyWorkspace(new long[][][] {{
+                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
+                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
+                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
+        }, {
+                {ids[1][0][0], ids[1][0][1], ids[1][0][3]},
+                {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
+                {ids[0][0][2], ids[0][1][2], -1},
+        }});
+    }
+
+    public void testWorkspace_items_not_merged_in_next_screen() throws Exception {
+        // First screen has 2 items that need to be moved, but second screen has only one
+        // empty space after migration (top-left corner)
+        long[][][] ids = createGrid(new int[][][]{{
+                {  0,  0,  0,  1},
+                {  3,  1,  0,  4},
+                { -1, -1, -1, -1},
+                {  5,  2, -1,  6},
+        },{
+                { -1,  0, -1,  1},
+                {  3,  1, -1,  4},
+                { -1, -1, -1, -1},
+                {  5,  2, -1,  6},
+        }});
+
+        new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
+                new Point(4, 4), new Point(3, 3)).migrateWorkspace();
+
+        // Items in the second column of the first screen should get placed on a new screen.
+        verifyWorkspace(new long[][][] {{
+                {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
+                {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
+                {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
+        }, {
+                {          -1, ids[1][0][1], ids[1][0][3]},
+                {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
+                {ids[1][3][0], ids[1][3][1], ids[1][3][3]},
+        }, {
+                {ids[0][0][2], ids[0][1][2], -1},
+        }});
+    }
+
+    /**
+     * Initializes the DB with dummy elements to represent the provided grid structure.
+     * @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
+     *                  type definitions. The first dimension represents the screens and the next
+     *                  two represent the workspace grid.
+     * @return the same grid representation where each entry is the corresponding item id.
+     */
+    private long[][][] createGrid(int[][][] typeArray) throws Exception {
+        long[][][] ids = new long[typeArray.length][][];
+
+        for (int i = 0; i < typeArray.length; i++) {
+            // Add screen to DB
+            long screenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
+            ContentValues v = new ContentValues();
+            v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
+            v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+            getMockContentResolver().insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v);
+
+            ids[i] = new long[typeArray[i].length][];
+            for (int y = 0; y < typeArray[i].length; y++) {
+                ids[i][y] = new long[typeArray[i][y].length];
+                for (int x = 0; x < typeArray[i][y].length; x++) {
+                    if (typeArray[i][y][x] < 0) {
+                        // Empty cell
+                        ids[i][y][x] = -1;
+                    } else {
+                        ids[i][y][x] = addItem(typeArray[i][y][x], screenId, DESKTOP, x, y);
+                    }
+                }
+            }
+        }
+        return ids;
+    }
+
+    /**
+     * Verifies that the workspace items are arranged in the provided order.
+     * @param ids A 3d array where the first dimension represents the screen, and the rest two
+     *            represent the workspace grid.
+     */
+    private void verifyWorkspace(long[][][] ids) {
+        ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(getMockContext());
+        assertEquals(ids.length, allScreens.size());
+        int total = 0;
+
+        for (int i = 0; i < ids.length; i++) {
+            long screenId = allScreens.get(i);
+            for (int y = 0; y < ids[i].length; y++) {
+                for (int x = 0; x < ids[i][y].length; x++) {
+                    long id = ids[i][y][x];
+
+                    Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                            new String[]{LauncherSettings.Favorites._ID},
+                            "container=-100 and screen=" + screenId +
+                                    " and cellX=" + x + " and cellY=" + y, null, null, null);
+                    if (id == -1) {
+                        assertEquals(0, c.getCount());
+                    } else {
+                        assertEquals(1, c.getCount());
+                        c.moveToNext();
+                        assertEquals(id, c.getLong(0));
+                        total++;
+                    }
+                    c.close();
+                }
+            }
+        }
+
+        // Verify that not other entry exist in the DB.
+        Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[]{LauncherSettings.Favorites._ID},
+                "container=-100", null, null, null);
+        assertEquals(total, c.getCount());
+        c.close();
+    }
+
+    /**
+     * Adds a dummy item in the DB.
+     * @param type {@link #APPLICATION} or {@link #SHORTCUT} or >= 2 for
+     *             folder (where the type represents the number of items in the folder).
+     */
+    private long addItem(int type, long screen, long container, int x, int y) throws Exception {
+        long id = LauncherAppState.getLauncherProvider().generateNewItemId();
+
+        ContentValues values = new ContentValues();
+        values.put(LauncherSettings.Favorites._ID, id);
+        values.put(LauncherSettings.Favorites.CONTAINER, container);
+        values.put(LauncherSettings.Favorites.SCREEN, screen);
+        values.put(LauncherSettings.Favorites.CELLX, x);
+        values.put(LauncherSettings.Favorites.CELLY, y);
+        values.put(LauncherSettings.Favorites.SPANX, 1);
+        values.put(LauncherSettings.Favorites.SPANY, 1);
+
+        if (type == APPLICATION || type == SHORTCUT) {
+            values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
+            values.put(LauncherSettings.Favorites.INTENT, VALID_INTENT);
+        } else {
+            values.put(LauncherSettings.Favorites.ITEM_TYPE,
+                    LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
+            // Add folder items.
+            for (int i = 0; i < type; i++) {
+                addItem(APPLICATION, 0, id, 0, 0);
+            }
+        }
+
+        getMockContentResolver().insert(LauncherSettings.Favorites.CONTENT_URI, values);
+        return id;
+    }
+}
diff --git a/tests/src/com/android/launcher3/util/TestLauncherProvider.java b/tests/src/com/android/launcher3/util/TestLauncherProvider.java
new file mode 100644
index 0000000..8758f55
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/TestLauncherProvider.java
@@ -0,0 +1,41 @@
+package com.android.launcher3.util;
+
+import android.content.Context;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherProvider;
+
+/**
+ * An extension of LauncherProvider backed up by in-memory database.
+ */
+public class TestLauncherProvider extends LauncherProvider {
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    protected synchronized void createDbIfNotExists() {
+        if (mOpenHelper == null) {
+            mOpenHelper = new MyDatabaseHelper(getContext());
+        }
+    }
+
+    @Override
+    protected void notifyListeners() { }
+
+    private static class MyDatabaseHelper extends DatabaseHelper {
+        public MyDatabaseHelper(Context context) {
+            super(context, null);
+        }
+
+        @Override
+        protected long getDefaultUserSerial() {
+            return 0;
+        }
+
+        @Override
+        protected void onEmptyDbCreated() { }
+    }
+}
\ No newline at end of file