Merge "Removing AccessibleTabView and some other dead code." into ub-now-queens
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 591d9b6..fb7ac3f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -88,7 +88,25 @@
             android:stateNotNeeded="true"
             android:theme="@style/Theme"
             android:windowSoftInputMode="adjustPan"
-            android:screenOrientation="nosensor">
+            android:screenOrientation="nosensor"
+            android:enabled="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY"/>
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="com.android.launcher3.LauncherExtension"
+            android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true"
+            android:stateNotNeeded="true"
+            android:theme="@style/Theme"
+            android:windowSoftInputMode="adjustPan"
+            android:screenOrientation="nosensor"
+            android:enabled="false">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.HOME" />
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 8cd8673..fa5fe73 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -63,4 +63,11 @@
             android:layout_height="match_parent"
             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" />
 </FrameLayout>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 9e98d42..f2d2dd8 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -83,4 +83,11 @@
             android:layout_height="match_parent"
             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" />
 </FrameLayout>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 6261541..87fa2ed 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -82,4 +82,12 @@
             android:layout_height="match_parent"
             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" />
+
 </FrameLayout>
diff --git a/res/layout/launcher_overlay.xml b/res/layout/launcher_overlay.xml
new file mode 100644
index 0000000..9ef0c9a
--- /dev/null
+++ b/res/layout/launcher_overlay.xml
@@ -0,0 +1,20 @@
+<?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"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/launcher_overlay_example.xml b/res/layout/launcher_overlay_example.xml
new file mode 100644
index 0000000..422f281
--- /dev/null
+++ b/res/layout/launcher_overlay_example.xml
@@ -0,0 +1,37 @@
+<?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"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <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 9207dde..8aa65a4 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Program is nie geïnstalleer nie."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Program is nie beskikbaar nie"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Afgelaaide program in veiligmodus gedeaktiveer"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Legstukke"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Legstukke"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Wys Mem"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 82765c2..0326109 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"ፍርግሞች"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ፍርግሞች"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 5d4ae42..919f0d0 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"الأدوات"</string>
     <string name="widget_adder" msgid="3201040140710381657">"الأدوات"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 1bdbb9c..6654f1d 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"Приспособления"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Приспособления"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 9cb31d7..019e82f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"L\'aplicació no està disponible."</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'aplicació que has baixat està desactivada al mode segur."</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"En Mode segur, els widgets estan desactivats."</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra la memòria"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index f5a0554..4b05436 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikace není nainstalována."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplikace není k dispozici."</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Stažená aplikace je v nouzovém režimu zakázána"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgety"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobrazit Mem"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index a9ded74..d5352f2 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installeret."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgængelig"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloadet app er deaktiveret i sikker tilstand"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis Mem"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 5bf1a7c..7e4ae47 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"App ist nicht installiert."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App nicht verfügbar"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Heruntergeladene App im abgesicherten Modus deaktiviert"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets im abgesicherten Modus deaktiviert"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Speicher anzeigen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 4916337..5a36332 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"Γραφικά στοιχεία"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Γραφικά στοιχεία"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 53b4620..7e21222 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 53b4620..7e21222 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index dd5575b..dc43f2d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"No se instaló la aplicación."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible."</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index e66b79e..67c283a 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"La aplicación no está instalada."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets inhabilitados en modo seguro"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index bd70aa4..1b9f1b7 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Rakendus pole installitud."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Rakendus ei ole saadaval"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Allalaetud rakendus on turvarežiimis keelatud"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Turvarežiimis on vidinad keelatud"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Vidinad"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Vidinad"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mälu kuvamine"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 5b428cc..c765d8f 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"برنامه نصب نشده است."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"برنامه در دسترس نیست"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"برنامه دانلود شده در حالت ایمن غیرفعال شد"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"ابزارک‌ها"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ابزارک‌ها"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"‏نمایش Mem"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 63eb3f5..0004501 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Sovellusta ei ole asennettu."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Sovellus ei ole käytettävissä"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ladattu sovellus poistettiin käytöstä suojatussa tilassa"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgetit poistettu käytöstä vikasietotilassa"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgetit"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgetit"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Näytä muisti"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index fb78002..c1070f2 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index ce657b9..064d751 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 7bf9c85..f14eff7 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"शॉर्टकट"</string>
     <string name="widget_adder" msgid="3201040140710381657">"शॉर्टकट"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"मेमोरी दिखाएं"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 62c1916..aa01648 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -26,6 +26,7 @@
     <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 onemogućena je u Sigurnom načinu rada"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgeti su onemogućeni u Sigurnom načinu rada"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgeti"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Prikaži mem"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 0dcd5df..4416ab0 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Az alkalmazás nincs telepítve."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Az alkalmazás nem érhető el"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"A letöltött alkalmazás Csökkentett módban ki van kapcsolva"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"A modulok ki vannak kapcsolva Csökkentett módban"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Modulok"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Modulok"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem. megjelenítése"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index bae306d..9402a42 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ներբեռնված ծրագիրն անջատված է Անվտանգ ռեժիմում"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Վիջեթներ"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index b8f6d96..2eb88c7 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplikasi tidak tersedia"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplikasi yang diunduh dinonaktifkan dalam mode Aman"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widget dinonaktifkan dalam mode Aman"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Tampilkan Memori"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 7cd03a8..aaddcfc 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"App non installata."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App non disponibile"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'app scaricata è stata disattivata in modalità provvisoria"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widget disabilitati in modalità provvisoria"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra Mem"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 44dfac7..fc059e0 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"רכיבי ווידג\'ט"</string>
     <string name="widget_adder" msgid="3201040140710381657">"רכיבי ווידג\'ט"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index e52a4ab..d8ee943 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"ウィジェット"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ウィジェット"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 5ac936c..8092331 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"აპი არ არის დაყენებული."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"აპი მიუწვდომელია"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"უსაფრთხო რეჟიმში ჩამოტვირთული აპი გაუქმებულია"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"ვიჯეტები"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 0aec2b0..390f0ee 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ​ Mem"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 88c4ded..d470283 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"위젯"</string>
     <string name="widget_adder" msgid="3201040140710381657">"위젯"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 41e41ce..935e997 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"ແອັບຯ​ໃຊ້​ບໍ່​ໄດ້"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"ແອັບຯ​ທີ່​ດາວ​ໂຫລດ​ແລ້ວ​ຖືກ​ປິດ​ການ​ນຳ​ໃຊ້​ໃນ Safe mode"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"ວິດເຈັດ"</string>
     <string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 145b700..6e47f67 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Programa neįdiegta."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Programa nepasiekiama"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Atsisiųsta programa išjungta Saugos režimu"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Valdikliai išjungti Saugiame režime"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Valdikliai"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Valdikliai"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rodyti atmintinę"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index af591e0..4079331 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Lietotne nav instalēta."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Lietotne nav pieejama."</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Lejupielādētā lietotne ir atspējota drošajā režīmā."</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Logrīki atspējoti drošajā režīmā"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Logrīki"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Logrīki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rādīt atmiņu"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index faa5276..a22b8fc 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -26,6 +26,7 @@
     <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">"Safe горимд виджетүүдийг идэвхгүйжүүлсэн"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Виджет"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виджет"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index d80feb9..1770e89 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Apl tidak tersedia"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Apl yang dimuat turun dilumpuhkan dalam mod Selamat"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Papar Mem"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index d0580a7..6211361 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installert."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgjengelig"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"En nedlastet app er deaktivert i sikker modus"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Moduler"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Moduler"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis minne"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index be588b2..3e0f640 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"App is niet geïnstalleerd."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"App is niet beschikbaar"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Gedownloade app uitgeschakeld in veilige modus"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets uitgeschakeld in Veilige modus"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Geheugen weergeven"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 793a371..ee48b24 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikacja nie jest zainstalowana."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplikacja niedostępna"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Pobrana aplikacja została wyłączona w trybie awaryjnym"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widżety są wyłączone w trybie bezpiecznym"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widżety"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widżety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaż pamięć"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 11acb47..e19fcea 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"A aplicação não está disponível"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicação transferida desativada no Modo de segurança"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets desativados no Modo de segurança"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar mem"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 64b9bb1..355e71a 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"O app não está disponível"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"App transferido por download desativado no modo de segurança"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memória"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 4e36a66..a509399 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplicația nu este disponibilă"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicația descărcată este dezactivată în modul de siguranță"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgeturile sunt dezactivate în modul de siguranță"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgeturi"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgeturi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afișați memoria"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c0ee48c..7cbd9fa 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Приложение удалено"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Приложение недоступно"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Скачанное приложение отключено в безопасном режиме"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Виджеты"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index e984278..e3c242d 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplikácia nie je k dispozícii"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Stiahnutá aplikácia je v núdzovom režime zakázaná"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Miniaplikácie"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Miniaplikácie"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobraziť pamäť"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 8047791..807b1b4 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Aplikacija ni nameščena."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Aplikacija ni na voljo"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Prenesena aplikacija je onemogočena v Varnem načinu"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Pripomočki"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Pripomočki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaži pomnilnik"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 31430fe..3509252 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 7f2af8a..572309d 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Appen är inte installerad."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Appen är inte tillgänglig"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Den hämtade appen inaktiverades i säkert läge"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets är inaktiverade i felsäkert läge"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widgetar"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widgetar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Visa Mem"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 485157b..0284679 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Programu haipatikani"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Programu iliyopakuliwa imezimwa katika Hali Salama"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Wijeti"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Wijeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Onyesha Kumbukumbu"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 26c72f4..bc9ddfb 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"วิดเจ็ต"</string>
     <string name="widget_adder" msgid="3201040140710381657">"วิดเจ็ต"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 27481be..9078d15 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Hindi naka-install ang app."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Hindi available ang app"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Naka-disable ang na-download na app sa Safe mode"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Naka-disable ang mga widget sa Safe mode"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Mga Widget"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Mga Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ipakita ang Mem"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 3bea496..b71748e 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Uygulama yüklü değil."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Uygulama kullanılamıyor"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"İndirilen uygulama Güvenli modda devre dışı bırakıldı"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"Widget\'lar"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Widget\'lar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Belleği Göster"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 86ca01b..78cda53 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"Віджети"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Віджети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index b8d0063..61715c8 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Ứng dụng chưa được cài đặt."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Ứng dụng không có sẵn"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Ứng dụng đã tải xuống bị tắt ở chế độ An toàn"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Tiện ích con bị vô hiệu hóa ở chế độ an toàn"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Tiện ích con"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Tiện ích con"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Hiển thị bộ nhớ"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index a098235..30e34b9 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,6 +26,8 @@
     <string name="activity_not_found" msgid="8071924732094499514">"未安装该应用。"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"应用不可用"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"安全模式下不允许使用下载的此应用"</string>
+    <!-- no translation found for safemode_widget_error (4863470563535682004) -->
+    <skip />
     <string name="widgets_tab_label" msgid="2921133187116603919">"小部件"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 796c72e..3656e2e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index ff3fa8c..f9fdaa4 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -26,6 +26,7 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 891f672..79f8b54 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -26,6 +26,7 @@
     <string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Uhlelo lokusebenza alutholakali"</string>
     <string name="safemode_shortcut_error" msgid="9160126848219158407">"Uhlelo lokusebenza olulandiwe lukhutshaziwe kumodi ephephile"</string>
+    <string name="safemode_widget_error" msgid="4863470563535682004">"Amawijethi akhutshaziwe kwimodi yokuphepha"</string>
     <string name="widgets_tab_label" msgid="2921133187116603919">"Amawijethi"</string>
     <string name="widget_adder" msgid="3201040140710381657">"Amawijethi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Bonisa i-Mem"</string>
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 1bd2907..7f3b7fb 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -728,7 +728,8 @@
                 !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
             // Exit spring loaded mode if we have not successfully dropped or have not handled the
             // drop in Workspace
-            mLauncher.exitSpringLoadedDragMode();
+            mLauncher.exitSpringLoadedDragModeDelayed(true,
+                    Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
             mLauncher.unlockScreenOrientation(false);
         } else {
             mLauncher.unlockScreenOrientation(false);
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 05e8906..ea058ea 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -21,8 +21,6 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -41,12 +39,8 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 
-import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.UserHandleCompat;
 
-import java.util.List;
-import java.util.Set;
-
 public class DeleteDropTarget extends ButtonDropTarget {
     private static int DELETE_ANIMATION_DURATION = 285;
     private static int FLING_DELETE_ANIMATION_DURATION = 350;
@@ -266,7 +260,7 @@
             public void run() {
                 completeDrop(d);
                 mSearchDropTargetBar.onDragEnd();
-                mLauncher.exitSpringLoadedDragMode();
+                mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null);
             }
         };
         dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 6d0a2be..480dce9 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -26,10 +26,16 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.util.Log;
-import android.view.*;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.inputmethod.InputMethodManager;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 
 /**
  * Class for initiating a drag within a view or across multiple views.
@@ -318,18 +324,17 @@
         }
         endDrag();
     }
-    public void onAppsRemoved(final ArrayList<String> packageNames, ArrayList<AppInfo> appInfos) {
+    public void onAppsRemoved(final ArrayList<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;
             if (rawDragInfo instanceof ShortcutInfo) {
                 ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
-                for (AppInfo info : appInfos) {
+                for (ComponentName componentName : cns) {
                     // Added null checks to prevent NPE we've seen in the wild
-                    if (dragInfo != null &&
-                            dragInfo.intent != null && info != null) {
+                    if (dragInfo != null && dragInfo.intent != null) {
                         ComponentName cn = dragInfo.intent.getComponent();
-                        boolean isSameComponent = cn != null && (cn.equals(info.componentName) ||
+                        boolean isSameComponent = cn != null && (cn.equals(componentName) ||
                                 packageNames.contains(cn.getPackageName()));
                         if (isSameComponent) {
                             cancelDrag();
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index a8a61ea..ff9072a 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -89,6 +89,8 @@
     private Drawable mLeftHoverDrawableActive;
     private Drawable mRightHoverDrawableActive;
 
+    private boolean mBlockTouches = false;
+
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -185,11 +187,19 @@
         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)) {
@@ -332,6 +342,10 @@
         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/Launcher.java b/src/com/android/launcher3/Launcher.java
index be84540..309837f 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -86,6 +86,7 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
@@ -125,6 +126,7 @@
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -227,6 +229,10 @@
 
     private boolean mIsSafeModeEnabled;
 
+    LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl();
+    LauncherOverlay mLauncherOverlay;
+    ViewGroup mLauncherOverlayView;
+
     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;
@@ -506,6 +512,13 @@
 
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onCreate(savedInstanceState);
+            if (mLauncherCallbacks.hasLauncherOverlay()) {
+                ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub);
+                mLauncherOverlayView = (ViewGroup) stub.inflate();
+                mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(mLauncherOverlayView,
+                        mLauncherOverlayCallbacks);
+                mWorkspace.setLauncherOverlay(mLauncherOverlay);
+            }
         }
     }
 
@@ -1144,6 +1157,84 @@
         boolean isScrollingAllowed();
     }
 
+    public interface LauncherOverlay {
+
+        /**
+         * Touch interaction leading to overscroll has begun
+         */
+        public void onScrollInteractionBegin();
+
+        /**
+         * Touch interaction related to overscroll has ended
+         */
+        public void onScrollInteractionEnd();
+
+        /**
+         * 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);
+
+        /**
+         * Screen has stopped scrolling
+         */
+        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 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();
+    }
+
+    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;
+            }
+            return false;
+        }
+
+        @Override
+        public void exitFullImmersion() {
+            mDragLayer.setBlockTouch(false);
+        }
+    }
+
     protected boolean hasSettings() {
         if (mLauncherCallbacks != null) {
             return mLauncherCallbacks.hasSettings();
@@ -2063,7 +2154,6 @@
         mWorkspace = null;
         mDragController = null;
 
-        PackageInstallerCompat.getInstance(this).onStop();
         LauncherAnimUtils.onDestroyActivity();
 
         if (mLauncherCallbacks != null) {
@@ -4084,11 +4174,8 @@
     }
 
     public View getQsbBar() {
-        if (mLauncherCallbacks != null) {
-            View qsb = mLauncherCallbacks.getQsbBar();
-            if (qsb != null) {
-                return qsb;
-            }
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            return mLauncherCallbacks.getQsbBar();
         }
 
         if (mQsb == null) {
@@ -4858,33 +4945,54 @@
             return;
         }
 
-        if (mWorkspace != null) {
-            mWorkspace.updateShortcutsAndWidgets(apps);
-        }
-
         if (!LauncherAppState.isDisableAllApps() &&
                 mAppsCustomizeContent != null) {
             mAppsCustomizeContent.updateApps(apps);
         }
     }
 
+    @Override
+    public void bindWidgetsRestored(final ArrayList<LauncherAppWidgetInfo> widgets) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindWidgetsRestored(widgets);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
+        }
+        mWorkspace.widgetsRestored(widgets);
+    }
+
     /**
      * Some shortcuts were updated in the background.
      *
      * Implementation of the method from LauncherModel.Callbacks.
      */
-    public void bindShortcutsUpdated(final ArrayList<ShortcutInfo> shortcuts) {
+    @Override
+    public void bindShortcutsChanged(final ArrayList<ShortcutInfo> updated,
+            final ArrayList<ShortcutInfo> removed, final UserHandleCompat user) {
         Runnable r = new Runnable() {
             public void run() {
-                bindShortcutsUpdated(shortcuts);
+                bindShortcutsChanged(updated, removed, user);
             }
         };
         if (waitUntilResume(r)) {
             return;
         }
 
-        if (mWorkspace != null) {
-            mWorkspace.updateShortcuts(shortcuts);
+        if (!updated.isEmpty()) {
+            mWorkspace.updateShortcuts(updated);
+        }
+
+        if (!removed.isEmpty()) {
+            HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
+            for (ShortcutInfo si : removed) {
+                removedComponents.add(si.getTargetComponent());
+            }
+            mWorkspace.removeItemsByComponentName(removedComponents, user);
+            // Notify the drag controller
+            mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents);
         }
     }
 
@@ -4935,19 +5043,23 @@
         }
 
         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 (!appInfos.isEmpty()) {
-                mWorkspace.removeItemsByApplicationInfo(appInfos, user);
+            if (!removedComponents.isEmpty()) {
+                mWorkspace.removeItemsByComponentName(removedComponents, user);
             }
+            // Notify the drag controller
+            mDragController.onAppsRemoved(packageNames, removedComponents);
+
         } else {
             mWorkspace.disableShortcutsByPackageName(packageNames, user, reason);
         }
 
-        // Notify the drag controller
-        mDragController.onAppsRemoved(packageNames, appInfos);
-
         // Update AllApps
         if (!LauncherAppState.isDisableAllApps() &&
                 mAppsCustomizeContent != null) {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 893d49f..03ab94b 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 
 import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
 
 import java.lang.ref.WeakReference;
@@ -134,6 +135,7 @@
         sContext.unregisterReceiver(mModel);
         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
         launcherApps.removeOnAppsChangedCallback(mModel);
+        PackageInstallerCompat.getInstance(sContext).onStop();
 
         ContentResolver resolver = sContext.getContentResolver();
         resolver.unregisterContentObserver(mFavoritesObserver);
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index aef2adc..e0cfa27 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -6,6 +6,7 @@
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.View;
+import android.view.ViewGroup;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -86,4 +87,22 @@
     public boolean overrideWallpaperDimensions();
     public boolean isLauncherPreinstalled();
 
+    /**
+     * 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 overlayView 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(ViewGroup overlayView,
+            Launcher.LauncherOverlayCallbacks callbacks);
+
 }
diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java
new file mode 100644
index 0000000..10bbd35
--- /dev/null
+++ b/src/com/android/launcher3/LauncherExtension.java
@@ -0,0 +1,354 @@
+package com.android.launcher3;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * This class represents a very trivial LauncherExtension. It primarily serves as a simple
+ * class to exercise the LauncherOverlay interface.
+ */
+public class LauncherExtension extends Launcher {
+
+    //------ Activity methods -------//
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        setLauncherCallbacks(new LauncherExtensionCallbacks());
+        super.onCreate(savedInstanceState);
+    }
+
+    public class LauncherExtensionCallbacks implements LauncherCallbacks {
+
+        LauncherExtensionOverlay mLauncherOverlay = new LauncherExtensionOverlay();
+
+        @Override
+        public void preOnCreate() {
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+        }
+
+        @Override
+        public void preOnResume() {
+        }
+
+        @Override
+        public void onResume() {
+        }
+
+        @Override
+        public void onStart() {
+        }
+
+        @Override
+        public void onStop() {
+        }
+
+        @Override
+        public void onPause() {
+        }
+
+        @Override
+        public void onDestroy() {
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+        }
+
+        @Override
+        public void onPostCreate(Bundle savedInstanceState) {
+        }
+
+        @Override
+        public void onNewIntent(Intent intent) {
+        }
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        }
+
+        @Override
+        public void onWindowFocusChanged(boolean hasFocus) {
+        }
+
+        @Override
+        public boolean onPrepareOptionsMenu(Menu menu) {
+            return false;
+        }
+
+        @Override
+        public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args) {
+        }
+
+        @Override
+        public void onHomeIntent() {
+        }
+
+        @Override
+        public boolean handleBackPressed() {
+            if (mLauncherOverlay.isOverlayPanelShowing()) {
+                mLauncherOverlay.hideOverlayPanel();
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void onLauncherProviderChange() {
+        }
+
+        @Override
+        public void finishBindingItems(boolean upgradePath) {
+        }
+
+        @Override
+        public void onClickAllAppsButton(View v) {
+        }
+
+        @Override
+        public void bindAllApplications(ArrayList<AppInfo> apps) {
+        }
+
+        @Override
+        public void onClickFolderIcon(View v) {
+        }
+
+        @Override
+        public void onClickAppShortcut(View v) {
+        }
+
+        @Override
+        public void onClickPagedViewIcon(View v) {
+        }
+
+        @Override
+        public void onClickWallpaperPicker(View v) {
+        }
+
+        @Override
+        public void onClickSettingsButton(View v) {
+        }
+
+        @Override
+        public void onClickAddWidgetButton(View v) {
+        }
+
+        @Override
+        public void onPageSwitch(View newPage, int newPageIndex) {
+        }
+
+        @Override
+        public void onWorkspaceLockedChanged() {
+        }
+
+        @Override
+        public void onDragStarted(View view) {
+        }
+
+        @Override
+        public void onInteractionBegin() {
+        }
+
+        @Override
+        public void onInteractionEnd() {
+        }
+
+        @Override
+        public boolean forceDisableVoiceButtonProxy() {
+            return false;
+        }
+
+        @Override
+        public boolean providesSearch() {
+            return true;
+        }
+
+        @Override
+        public boolean startSearch(String initialQuery, boolean selectInitialQuery,
+                Bundle appSearchData, Rect sourceBounds) {
+            return false;
+        }
+
+        @Override
+        public void startVoice() {
+        }
+
+        @Override
+        public boolean hasCustomContentToLeft() {
+            return false;
+        }
+
+        @Override
+        public void populateCustomContentContainer() {
+        }
+
+        @Override
+        public View getQsbBar() {
+            return mLauncherOverlay.getSearchBox();
+        }
+
+        @Override
+        public Intent getFirstRunActivity() {
+            return null;
+        }
+
+        @Override
+        public boolean hasFirstRunActivity() {
+            return false;
+        }
+
+        @Override
+        public boolean hasDismissableIntroScreen() {
+            return false;
+        }
+
+        @Override
+        public View getIntroScreen() {
+            return null;
+        }
+
+        @Override
+        public boolean shouldMoveToDefaultScreenOnHomeIntent() {
+            return true;
+        }
+
+        @Override
+        public boolean hasSettings() {
+            return false;
+        }
+
+        @Override
+        public ComponentName getWallpaperPickerComponent() {
+            return null;
+        }
+
+        @Override
+        public boolean overrideWallpaperDimensions() {
+            return false;
+        }
+
+        @Override
+        public boolean isLauncherPreinstalled() {
+            return false;
+        }
+
+        @Override
+        public boolean hasLauncherOverlay() {
+            return true;
+        }
+
+        @Override
+        public LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
+                LauncherOverlayCallbacks callbacks) {
+
+            mLauncherOverlay.setOverlayCallbacks(callbacks);
+            mLauncherOverlay.setOverlayView(overlayView);
+
+            return mLauncherOverlay;
+        }
+
+        class LauncherExtensionOverlay implements LauncherOverlay {
+            LauncherOverlayCallbacks mLauncherOverlayCallbacks;
+            ViewGroup mOverlayView;
+            View mSearchBox;
+            View mSearchOverlay;
+            boolean mShowOverlayFeedback;
+            int mProgress;
+            boolean mOverlayPanelShowing;
+
+            @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 setOverlayView(ViewGroup overlayView) {
+                mOverlayView = (ViewGroup) getLayoutInflater().inflate(
+                        R.layout.launcher_overlay_example, overlayView);
+                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;
+            }
+        };
+    }
+}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index f0899a8..17670d2 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -198,7 +198,9 @@
                                   ArrayList<ItemInfo> addAnimated,
                                   ArrayList<AppInfo> addedApps);
         public void bindAppsUpdated(ArrayList<AppInfo> apps);
-        public void bindShortcutsUpdated(ArrayList<ShortcutInfo> shortcuts);
+        public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
+                ArrayList<ShortcutInfo> removed, UserHandleCompat user);
+        public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
         public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
         public void updatePackageBadge(String packageName);
         public void bindComponentsRemoved(ArrayList<String> packageNames,
@@ -373,15 +375,6 @@
             return;
         }
 
-        final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
-        Iterator<AppInfo> iter = allAppsApps.iterator();
-        while (iter.hasNext()) {
-            ItemInfo a = iter.next();
-            if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {
-                restoredAppsFinal.add((AppInfo) a);
-            }
-        }
-
         // Process the newly added applications and add them to the database first
         Runnable r = new Runnable() {
             public void run() {
@@ -389,16 +382,6 @@
                     public void run() {
                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                         if (callbacks == cb && cb != null) {
-                            if (!restoredAppsFinal.isEmpty()) {
-                                for (AppInfo info : restoredAppsFinal) {
-                                    final Intent intent = info.getIntent();
-                                    if (intent != null) {
-                                        mIconCache.deletePreloadedIcon(intent.getComponent(),
-                                                info.user);
-                                    }
-                                }
-                                callbacks.bindAppsUpdated(restoredAppsFinal);
-                            }
                             callbacks.bindAppsAdded(null, null, null, allAppsApps);
                         }
                     }
@@ -423,7 +406,6 @@
             public void run() {
                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
-                final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
 
                 // Get the list of workspace screens.  We need to append to this list and
                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
@@ -443,12 +425,7 @@
                         final Intent launchIntent = a.getIntent();
 
                         // Short-circuit this logic if the icon exists somewhere on the workspace
-                        if (LauncherModel.shortcutExists(context, name, launchIntent)) {
-                            // Only InstallShortcutReceiver sends us shortcutInfos, ignore them
-                            if (a instanceof AppInfo &&
-                                    LauncherModel.appWasPromise(context, launchIntent, a.user)) {
-                                restoredAppsFinal.add((AppInfo) a);
-                            }
+                        if (shortcutExists(context, name, launchIntent)) {
                             continue;
                         }
 
@@ -524,9 +501,6 @@
                                 }
                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
                                         addNotAnimated, addAnimated, null);
-                                if (!restoredAppsFinal.isEmpty()) {
-                                    callbacks.bindAppsUpdated(restoredAppsFinal);
-                                }
                             }
                         }
                     });
@@ -902,17 +876,6 @@
     }
 
     /**
-     * Returns true if the promise shortcuts with the same package name exists on the workspace.
-     */
-    static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {
-        final ComponentName component = intent.getComponent();
-        if (component == null) {
-            return false;
-        }
-        return !getItemsByPackageName(component.getPackageName(), user).isEmpty();
-    }
-
-    /**
      * Returns an ItemInfo array containing all the items in the LauncherModel.
      * The ItemInfo.id is not set through this function.
      */
@@ -1111,7 +1074,7 @@
      * @param context
      * @param item
      */
-    static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {
+    static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
         final ContentResolver cr = context.getContentResolver();
 
         Runnable r = new Runnable() {
@@ -3048,6 +3011,9 @@
                 return;
             }
 
+            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
+                    new HashMap<ComponentName, AppInfo>();
+
             if (added != null) {
                 // Ensure that we add all the workspace applications to the db
                 if (LauncherAppState.isDisableAllApps()) {
@@ -3056,23 +3022,15 @@
                 } else {
                     addAppsToAllApps(context, added);
                 }
+                for (AppInfo ai : added) {
+                    addedOrUpdatedApps.put(ai.componentName, ai);
+                }
             }
 
             if (modified != null) {
                 final ArrayList<AppInfo> modifiedFinal = modified;
-
-                // Update the launcher db to reflect the changes
-                for (AppInfo a : modifiedFinal) {
-                    ArrayList<ItemInfo> infos =
-                            getItemInfoForComponentName(a.componentName, mUser);
-                    for (ItemInfo i : infos) {
-                        if (i instanceof ShortcutInfo && isShortcutAppTarget((ShortcutInfo) i)) {
-                            ShortcutInfo info = (ShortcutInfo) i;
-                            info.title = a.title.toString();
-                            info.contentDescription = a.contentDescription;
-                            updateItemInDatabase(context, info);
-                        }
-                    }
+                for (AppInfo ai : modified) {
+                    addedOrUpdatedApps.put(ai.componentName, ai);
                 }
 
                 mHandler.post(new Runnable() {
@@ -3085,37 +3043,128 @@
                 });
             }
 
-            // Update shortcuts which use an iconResource
+            // Update shortcut infos
             if (mOp == OP_ADD || mOp == OP_UPDATE) {
-                final ArrayList<ShortcutInfo> iconsChanged = new ArrayList<ShortcutInfo>();
+                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));
-                // We need to iterate over the items here, so that we can avoid new Bitmap
-                // creation on the UI thread.
                 synchronized (sBgLock) {
-                    for (ItemInfo info : sBgWorkspaceItems) {
+                    for (ItemInfo info : sBgItemsIdMap.values()) {
                         if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
                             ShortcutInfo si = (ShortcutInfo) info;
+                            boolean infoUpdated = false;
+                            boolean shortcutUpdated = false;
+
+                            // Update shortcuts which use iconResource.
                             if ((si.iconResource != null)
-                                    && packageSet.contains(si.getTargetComponent().getPackageName())){
+                                    && packageSet.contains(si.iconResource.packageName)) {
                                 Bitmap icon = Utilities.createIconBitmap(si.iconResource.packageName,
                                         si.iconResource.resourceName, mIconCache, context);
                                 if (icon != null) {
                                     si.setIcon(icon);
                                     si.usingFallbackIcon = false;
-                                    iconsChanged.add(si);
-                                    updateItemInDatabase(context, si);
+                                    infoUpdated = true;
                                 }
                             }
+
+                            ComponentName cn = si.getTargetComponent();
+                            if (cn != null && packageSet.contains(cn.getPackageName())) {
+                                AppInfo appInfo = addedOrUpdatedApps.get(cn);
+
+                                if (si.isPromise()) {
+                                    mIconCache.deletePreloadedIcon(cn, mUser);
+                                    if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+                                        // Auto install icon
+                                        PackageManager pm = context.getPackageManager();
+                                        ResolveInfo matched = pm.resolveActivity(
+                                                new Intent(Intent.ACTION_MAIN)
+                                                .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
+                                                PackageManager.MATCH_DEFAULT_ONLY);
+                                        if (matched == null) {
+                                            // Try to find the best match activity.
+                                            Intent intent = pm.getLaunchIntentForPackage(
+                                                    cn.getPackageName());
+                                            if (intent != null) {
+                                                cn = intent.getComponent();
+                                                appInfo = addedOrUpdatedApps.get(cn);
+                                            }
+
+                                            if ((intent == null) || (appInfo == null)) {
+                                                removedShortcuts.add(si);
+                                                continue;
+                                            }
+                                            si.promisedIntent = intent;
+                                        }
+                                    }
+
+                                    // Restore the shortcut.
+                                    si.intent = si.promisedIntent;
+                                    si.promisedIntent = null;
+                                    si.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
+                                            & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
+                                            & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+
+                                    infoUpdated = true;
+                                    si.updateIcon(mIconCache);
+                                }
+
+                                if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
+                                        && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+                                    si.updateIcon(mIconCache);
+                                    si.title = appInfo.title.toString();
+                                    si.contentDescription = appInfo.contentDescription;
+                                    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;
+                                    shortcutUpdated = true;
+                                }
+                            }
+
+                            if (infoUpdated || shortcutUpdated) {
+                                updatedShortcuts.add(si);
+                            }
+                            if (infoUpdated) {
+                                updateItemInDatabase(context, si);
+                            }
+                        } else if (info instanceof LauncherAppWidgetInfo) {
+                            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
+                            if (mUser.equals(widgetInfo.user)
+                                    && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
+                                    && packageSet.contains(widgetInfo.providerName.getPackageName())) {
+                                widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+                                widgets.add(widgetInfo);
+                                updateItemInDatabase(context, widgetInfo);
+                            }
                         }
                     }
                 }
 
-                if (!iconsChanged.isEmpty()) {
+                if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
+                    mHandler.post(new Runnable() {
+
+                        public void run() {
+                            Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                            if (callbacks == cb && cb != null) {
+                                callbacks.bindShortcutsChanged(
+                                        updatedShortcuts, removedShortcuts, mUser);
+                            }
+                        }
+                    });
+                    if (!removedShortcuts.isEmpty()) {
+                        deleteItemsFromDatabase(context, removedShortcuts);
+                    }
+                }
+                if (!widgets.isEmpty()) {
                     mHandler.post(new Runnable() {
                         public void run() {
                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                             if (callbacks == cb && cb != null) {
-                                callbacks.bindShortcutsUpdated(iconsChanged);
+                                callbacks.bindWidgetsRestored(widgets);
                             }
                         }
                     });
@@ -3415,20 +3464,6 @@
     }
 
     /**
-     * @return true if the ShortcutInfo points to an app shortcut target, i.e. it has been added by
-     * dragging from AllApps list.
-     */
-    public static boolean isShortcutAppTarget(ShortcutInfo info) {
-        // We need to check for ACTION_MAIN otherwise getComponent() might
-        // return null for some shortcuts (for instance, for shortcuts to
-        // web pages.)
-        Intent intent = info.promisedIntent != null ? info.promisedIntent : info.intent;
-        ComponentName name = intent.getComponent();
-        return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
-                Intent.ACTION_MAIN.equals(intent.getAction()) && name != null;
-    }
-
-    /**
      * Make an ShortcutInfo object for a shortcut that isn't an application.
      */
     private ShortcutInfo getShortcutInfo(Cursor c, Context context,
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 48fc0c9..7d65f46 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -204,6 +204,8 @@
 
     protected boolean mAllowLongPress = true;
 
+    private boolean mWasInOverscroll = false;
+
     // Page Indicator
     private int mPageIndicatorViewId;
     private PageIndicator mPageIndicator;
@@ -625,6 +627,7 @@
 
     // a method that subclasses can override to add behavior
     protected void onPageEndMoving() {
+        mWasInOverscroll = false;
     }
 
     /**
@@ -663,6 +666,7 @@
         if (isXBeforeFirstPage) {
             super.scrollTo(0, y);
             if (mAllowOverScroll) {
+                mWasInOverscroll = true;
                 if (isRtl) {
                     overScroll(x - mMaxScrollX);
                 } else {
@@ -672,6 +676,7 @@
         } else if (isXAfterLastPage) {
             super.scrollTo(mMaxScrollX, y);
             if (mAllowOverScroll) {
+                mWasInOverscroll = true;
                 if (isRtl) {
                     overScroll(x);
                 } else {
@@ -679,6 +684,10 @@
                 }
             }
         } else {
+            if (mWasInOverscroll) {
+                overScroll(0);
+                mWasInOverscroll = false;
+            }
             mOverScrollX = x;
             super.scrollTo(x, y);
         }
@@ -1513,6 +1522,7 @@
                 mLastMotionXRemainder = 0;
                 mTouchX = getViewportOffsetX() + getScrollX();
                 mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                onScrollInteractionBegin();
                 pageBeginMoving();
             }
         }
@@ -1752,6 +1762,7 @@
             mActivePointerId = ev.getPointerId(0);
 
             if (mTouchState == TOUCH_STATE_SCROLLING) {
+                onScrollInteractionBegin();
                 pageBeginMoving();
             }
             break;
@@ -1940,6 +1951,7 @@
                             getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
                     invalidate();
                 }
+                onScrollInteractionEnd();
             } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
                 // at this point we have not moved beyond the touch slop
                 // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
@@ -2025,6 +2037,15 @@
         mActivePointerId = INVALID_POINTER;
     }
 
+    /**
+     * Triggered by scrolling via touch
+     */
+    protected void onScrollInteractionBegin() {
+    }
+
+    protected void onScrollInteractionEnd() {
+    }
+
     protected void onUnhandledTap(MotionEvent ev) {
         ((Launcher) getContext()).onClick(this);
     }
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 435dbda..6205088 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -37,7 +38,7 @@
     private static final int sTransitionOutDuration = 175;
 
     private ObjectAnimator mDropTargetBarAnim;
-    private ObjectAnimator mQSBSearchBarAnim;
+    private ValueAnimator mQSBSearchBarAnim;
     private static final AccelerateInterpolator sAccelerateInterpolator =
             new AccelerateInterpolator();
 
@@ -70,28 +71,38 @@
         mInfoDropTarget.setLauncher(launcher);
         mDeleteDropTarget.setLauncher(launcher);
         mQSBSearchBar = launcher.getQsbBar();
-        if (mEnableDropDownDropTargets) {
-            mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
-                    -mBarHeight);
+        if (mQSBSearchBar != null) {
+            if (mEnableDropDownDropTargets) {
+                mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
+                        -mBarHeight);
+            } else {
+                mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+            }
+            setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
         } else {
-            mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+            // Create a no-op animation of the search bar is null
+            mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0);
+            mQSBSearchBarAnim.setDuration(sTransitionInDuration);
         }
-        setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
     }
 
     private void prepareStartAnimation(View v) {
         // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
         // callback below)
-        v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        if (v != null) {
+            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        }
     }
 
-    private void setupAnimation(ObjectAnimator anim, final View v) {
+    private void setupAnimation(ValueAnimator anim, final View v) {
         anim.setInterpolator(sAccelerateInterpolator);
         anim.setDuration(sTransitionInDuration);
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                v.setLayerType(View.LAYER_TYPE_NONE, null);
+                if (v != null) {
+                    v.setLayerType(View.LAYER_TYPE_NONE, null);
+                }
             }
         });
     }
@@ -145,9 +156,9 @@
             mQSBSearchBarAnim.reverse();
         } else {
             mQSBSearchBarAnim.cancel();
-            if (mEnableDropDownDropTargets) {
+            if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
                 mQSBSearchBar.setTranslationY(0);
-            } else {
+            } else if (mQSBSearchBar != null) {
                 mQSBSearchBar.setAlpha(1f);
             }
         }
@@ -161,9 +172,9 @@
             mQSBSearchBarAnim.start();
         } else {
             mQSBSearchBarAnim.cancel();
-            if (mEnableDropDownDropTargets) {
+            if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
                 mQSBSearchBar.setTranslationY(-mBarHeight);
-            } else {
+            } else if (mQSBSearchBar != null) {
                 mQSBSearchBar.setAlpha(0f);
             }
         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2683bec..518ee97 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -67,6 +67,7 @@
 
 import com.android.launcher3.FolderIcon.FolderRingAnimator;
 import com.android.launcher3.Launcher.CustomContentCallbacks;
+import com.android.launcher3.Launcher.LauncherOverlay;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.compat.PackageInstallerCompat;
 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
@@ -289,6 +290,12 @@
     private boolean mDeferDropAfterUninstall;
     private boolean mUninstallSuccessful;
 
+    // State related to Launcher Overlay
+    LauncherOverlay mLauncherOverlay;
+    boolean mScrollInteractionBegan;
+    boolean mStartedSendingScrollEvents;
+    boolean mShouldSendPageSettled;
+
     private final Runnable mBindPages = new Runnable() {
         @Override
         public void run() {
@@ -1249,6 +1256,58 @@
             stripEmptyScreens();
             mStripScreensOnPageStopMoving = false;
         }
+
+        if (mShouldSendPageSettled) {
+            mLauncherOverlay.onScrollSettled();
+            mShouldSendPageSettled = false;
+        }
+    }
+
+    protected void onScrollInteractionBegin() {
+        super.onScrollInteractionEnd();
+        mScrollInteractionBegan = true;
+    }
+
+    protected void onScrollInteractionEnd() {
+        super.onScrollInteractionEnd();
+        mScrollInteractionBegan = false;
+        if (mStartedSendingScrollEvents) {
+            mStartedSendingScrollEvents = false;
+            mLauncherOverlay.onScrollInteractionEnd();
+        }
+    }
+
+    public void setLauncherOverlay(LauncherOverlay overlay) {
+        mLauncherOverlay = overlay;
+    }
+
+    @Override
+    protected void overScroll(float amount) {
+        boolean isRtl = isLayoutRtl();
+        boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) ||
+                (amount >= 0 && (!hasCustomContent() || !isRtl));
+
+        boolean shouldScrollOverlay = (amount <= 0 && mLauncherOverlay != null && !isRtl) ||
+                (amount >= 0 && mLauncherOverlay != null && isRtl);
+
+        if (shouldScrollOverlay) {
+            if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
+                mStartedSendingScrollEvents = true;
+                mLauncherOverlay.onScrollInteractionBegin();
+                mShouldSendPageSettled = true;
+            }
+            int screenSize = getViewportWidth();
+            float f = (amount / screenSize);
+
+            int progress = (int) Math.abs((f * 100));
+
+            mLauncherOverlay.onScrollChange(progress, isRtl);
+        } else if (shouldOverScroll) {
+            dampedOverScroll(amount);
+            mOverScrollEffect = acceleratedOverFactor(amount);
+        } else {
+            mOverScrollEffect = 0;
+        }
     }
 
     @Override
@@ -1710,18 +1769,6 @@
         }
     }
 
-    @Override
-    protected void overScroll(float amount) {
-        boolean shouldOverScroll = (amount < 0 && (!hasCustomContent() || isLayoutRtl())) ||
-                (amount > 0 && (!hasCustomContent() || !isLayoutRtl()));
-        if (shouldOverScroll) {
-            dampedOverScroll(amount);
-            mOverScrollEffect = acceleratedOverFactor(amount);
-        } else {
-            mOverScrollEffect = 0;
-        }
-    }
-
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         mWindowToken = getWindowToken();
@@ -2353,10 +2400,6 @@
                 .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
             hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
 
-            Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
-                .alpha(finalSearchBarAlpha).withLayer();
-            searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
-
             Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
                 .alpha(finalOverviewPanelAlpha).withLayer();
             overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
@@ -2364,11 +2407,9 @@
             // For animation optimations, we may need to provide the Launcher transition
             // with a set of views on which to force build layers in certain scenarios.
             hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             if (layerViews != null) {
                 layerViews.add(hotseat);
-                layerViews.add(searchBar);
                 layerViews.add(overviewPanel);
             }
 
@@ -2385,11 +2426,21 @@
             overviewPanelAlpha.setDuration(duration);
             pageIndicatorAlpha.setDuration(duration);
             hotseatAlpha.setDuration(duration);
-            searchBarAlpha.setDuration(duration);
+
+            if (searchBar != null) {
+                Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
+                    .alpha(finalSearchBarAlpha).withLayer();
+                searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
+                searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                if (layerViews != null) {
+                    layerViews.add(searchBar);
+                }
+                searchBarAlpha.setDuration(duration);
+                anim.play(searchBarAlpha);
+            }
 
             anim.play(overviewPanelAlpha);
             anim.play(hotseatAlpha);
-            anim.play(searchBarAlpha);
             anim.play(pageIndicatorAlpha);
             anim.setStartDelay(delay);
         } else {
@@ -4693,20 +4744,11 @@
         removeItemsByComponentName(cns, user);
     }
 
-    // Removes items that match the application info specified, when applications are removed
-    // as a part of an update, this is called to ensure that other widgets and application
-    // shortcuts are not removed.
-    void removeItemsByApplicationInfo(final ArrayList<AppInfo> appInfos, UserHandleCompat user) {
-        // Just create a hash table of all the specific components that this will affect
-        HashSet<ComponentName> cns = new HashSet<ComponentName>();
-        for (AppInfo info : appInfos) {
-            cns.add(info.componentName);
-        }
-
-        // Remove all the things
-        removeItemsByComponentName(cns, user);
-    }
-
+    /**
+     * Removes items that match the item info specified. When applications are removed
+     * as a part of an update, this is called to ensure that other widgets and application
+     * shortcuts are not removed.
+     */
     void removeItemsByComponentName(final HashSet<ComponentName> componentNames,
             final UserHandleCompat user) {
         ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
@@ -4827,7 +4869,6 @@
         }
     }
 
-
     void updateShortcuts(ArrayList<ShortcutInfo> shortcuts) {
         final HashSet<ShortcutInfo> updates = new HashSet<ShortcutInfo>(shortcuts);
         mapOverItems(MAP_RECURSE, new ItemOperator() {
@@ -4835,9 +4876,12 @@
             public boolean evaluate(ItemInfo info, View v, View parent) {
                 if (info instanceof ShortcutInfo && v instanceof BubbleTextView &&
                         updates.contains(info)) {
-                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+                    ShortcutInfo si = (ShortcutInfo) info;
                     BubbleTextView shortcut = (BubbleTextView) v;
-                    shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
+                    boolean oldPromiseState = shortcut.getCompoundDrawables()[1]
+                            instanceof PreloadIconDrawable;
+                    shortcut.applyFromShortcutInfo(si, mIconCache, true,
+                            si.isPromise() != oldPromiseState);
 
                     if (parent != null) {
                         parent.invalidate();
@@ -4849,125 +4893,6 @@
         });
     }
 
-    void updateShortcutsAndWidgets(ArrayList<AppInfo> apps) {
-        // Break the appinfo list per user
-        final HashMap<UserHandleCompat, ArrayList<AppInfo>> appsPerUser =
-                new HashMap<UserHandleCompat, ArrayList<AppInfo>>();
-        for (AppInfo info : apps) {
-            ArrayList<AppInfo> filtered = appsPerUser.get(info.user);
-            if (filtered == null) {
-                filtered = new ArrayList<AppInfo>();
-                appsPerUser.put(info.user, filtered);
-            }
-            filtered.add(info);
-        }
-
-        for (Map.Entry<UserHandleCompat, ArrayList<AppInfo>> entry : appsPerUser.entrySet()) {
-            updateShortcutsAndWidgetsPerUser(entry.getValue(), entry.getKey());
-        }
-    }
-
-    private void updateShortcutsAndWidgetsPerUser(ArrayList<AppInfo> apps,
-            final UserHandleCompat user) {
-        // Create a map of the apps to test against
-        final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
-        final HashSet<String> pkgNames = new HashSet<String>();
-        for (AppInfo ai : apps) {
-            appsMap.put(ai.componentName, ai);
-            pkgNames.add(ai.componentName.getPackageName());
-        }
-        final HashSet<ComponentName> iconsToRemove = new HashSet<ComponentName>();
-
-        mapOverItems(MAP_RECURSE, new ItemOperator() {
-            @Override
-            public boolean evaluate(ItemInfo info, View v, View parent) {
-                if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
-                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
-                    ComponentName cn = shortcutInfo.getTargetComponent();
-                    AppInfo appInfo = appsMap.get(cn);
-                    if (user.equals(shortcutInfo.user) && cn != null
-                            && pkgNames.contains(cn.getPackageName())) {
-                        boolean promiseStateChanged = false;
-                        boolean infoUpdated = false;
-                        if (shortcutInfo.isPromise()) {
-                            if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
-                                // Auto install icon
-                                PackageManager pm = getContext().getPackageManager();
-                                ResolveInfo matched = pm.resolveActivity(
-                                        new Intent(Intent.ACTION_MAIN)
-                                        .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
-                                        PackageManager.MATCH_DEFAULT_ONLY);
-                                if (matched == null) {
-                                    // Try to find the best match activity.
-                                    Intent intent = pm.getLaunchIntentForPackage(
-                                            cn.getPackageName());
-                                    if (intent != null) {
-                                        cn = intent.getComponent();
-                                        appInfo = appsMap.get(cn);
-                                    }
-
-                                    if ((intent == null) || (appsMap == null)) {
-                                        // Could not find a default activity. Remove this item.
-                                        iconsToRemove.add(shortcutInfo.getTargetComponent());
-
-                                        // process next shortcut.
-                                        return false;
-                                    }
-                                    shortcutInfo.promisedIntent = intent;
-                                }
-                            }
-
-                            // Restore the shortcut.
-                            shortcutInfo.intent = shortcutInfo.promisedIntent;
-                            shortcutInfo.promisedIntent = null;
-                            shortcutInfo.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
-                                    & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
-                                    & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
-
-                            promiseStateChanged = true;
-                            infoUpdated = true;
-                            shortcutInfo.updateIcon(mIconCache);
-                            LauncherModel.updateItemInDatabase(getContext(), shortcutInfo);
-                        }
-
-                        if ((shortcutInfo.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
-                            // Since package was just updated, the target must be available now.
-                            shortcutInfo.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
-                            infoUpdated = true;
-                        }
-
-                        // Only update the icon and labels if the shortcuts points to an app target
-                        if ((appInfo != null) && LauncherModel.isShortcutAppTarget(shortcutInfo)) {
-                            shortcutInfo.updateIcon(mIconCache);
-                            shortcutInfo.title = appInfo.title.toString();
-                            shortcutInfo.contentDescription = appInfo.contentDescription;
-                            infoUpdated = true;
-                        }
-
-                        if (infoUpdated) {
-                            BubbleTextView shortcut = (BubbleTextView) v;
-                            shortcut.applyFromShortcutInfo(shortcutInfo,
-                                    mIconCache, true, promiseStateChanged);
-
-                            if (parent != null) {
-                                parent.invalidate();
-                            }
-                        }
-                    }
-                }
-                // process all the shortcuts
-                return false;
-            }
-        });
-
-        if (!iconsToRemove.isEmpty()) {
-            removeItemsByComponentName(iconsToRemove, user);
-        }
-        if (user.equals(UserHandleCompat.myUserHandle())) {
-            restorePendingWidgets(pkgNames);
-        }
-    }
-
     public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
         ArrayList<String> packages = new ArrayList<String>(1);
         packages.add(packageName);
@@ -5008,9 +4933,11 @@
     }
 
     public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) {
-        HashSet<String> completedPackages = new HashSet<String>();
-
         for (final PackageInstallInfo installInfo : installInfos) {
+            if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
+                continue;
+            }
+
             mapOverItems(MAP_RECURSE, new ItemOperator() {
                 @Override
                 public boolean evaluate(ItemInfo info, View v, View parent) {
@@ -5038,42 +4965,10 @@
                     return false;
                 }
             });
-
-            if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
-                completedPackages.add(installInfo.packageName);
-            }
-        }
-
-        // Note that package states are sent only for myUser
-        if (!completedPackages.isEmpty()) {
-            restorePendingWidgets(completedPackages);
         }
     }
 
-    private void restorePendingWidgets(final Set<String> installedPackaged) {
-        final ArrayList<LauncherAppWidgetInfo> changedInfo = new ArrayList<LauncherAppWidgetInfo>();
-
-        // Iterate non recursively as widgets can't be inside a folder.
-        mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
-
-            @Override
-            public boolean evaluate(ItemInfo info, View v, View parent) {
-                if (info instanceof LauncherAppWidgetInfo) {
-                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
-                    if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
-                            && installedPackaged.contains(widgetInfo.providerName.getPackageName())) {
-
-                        changedInfo.add(widgetInfo);
-
-                        // Remove the provider not ready flag
-                        widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
-                        LauncherModel.updateItemInDatabase(getContext(), widgetInfo);
-                    }
-                }
-                // process all the widget
-                return false;
-            }
-        });
+    void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
         if (!changedInfo.isEmpty()) {
             DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
                     mLauncher.getAppWidgetHost());
@@ -5083,6 +4978,13 @@
                 widgetRefresh.run();
             } else {
                 // widgetRefresh will automatically run when the packages are updated.
+                // For now just update the progress bars
+                for (LauncherAppWidgetInfo info : changedInfo) {
+                    if (info.hostView instanceof PendingAppWidgetHostView) {
+                        info.installProgress = 100;
+                        ((PendingAppWidgetHostView) info.hostView).applyState();
+                    }
+                }
             }
         }
     }