Merge "Updating ItemInfo objects in the worker thread" into ub-now-queens
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index d5c7cd9..fa8ec64 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -202,7 +202,7 @@
     }
 
     public static String getSharedPreferencesKey() {
-        return WallpaperCropActivity.class.getName();
+        return LauncherFiles.WALLPAPER_CROP_PREFERENCES_KEY;
     }
 
     // As a ratio of screen height, the total distance we want the parallax effect to span
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 0728537..09e0963 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -86,8 +86,6 @@
     public static final int PICK_LIVE_WALLPAPER = 7;
     private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
     private static final String SELECTED_INDEX = "SELECTED_INDEX";
-    private static final String OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb.jpg";
-    private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb2.jpg";
     private static final int FLAG_POST_DELAY_MILLIS = 200;
 
     private View mSelectedTile;
@@ -999,16 +997,16 @@
 
     private File getDefaultThumbFile() {
         return new File(getFilesDir(), Build.VERSION.SDK_INT
-                + "_" + DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
+                + "_" + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL);
     }
 
     private boolean saveDefaultWallpaperThumb(Bitmap b) {
         // Delete old thumbnails.
-        new File(getFilesDir(), OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
-        new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+        new File(getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL_OLD).delete();
+        new File(getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
 
         for (int i = Build.VERSION_CODES.JELLY_BEAN; i < Build.VERSION.SDK_INT; i++) {
-            new File(getFilesDir(), i + "_" + DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+            new File(getFilesDir(), i + "_" + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
         }
         return writeImageToFileAsJpeg(getDefaultThumbFile(), b);
     }
diff --git a/res/drawable-hdpi/hand.png b/res/drawable-hdpi/hand.png
deleted file mode 100644
index bd4f6df..0000000
--- a/res/drawable-hdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_focused_holo.9.png b/res/drawable-hdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 673e3bf..0000000
--- a/res/drawable-hdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_holo.9.png b/res/drawable-hdpi/tab_selected_holo.9.png
deleted file mode 100644
index d57df98..0000000
--- a/res/drawable-hdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 4b312d9..0000000
--- a/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 6278eef..0000000
--- a/res/drawable-hdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index 294991d..0000000
--- a/res/drawable-hdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_holo.9.png b/res/drawable-hdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 19532ab..0000000
--- a/res/drawable-hdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index 5140b35..0000000
--- a/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index aadc6f8..0000000
--- a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/hand.png b/res/drawable-mdpi/hand.png
deleted file mode 100644
index fe5a035..0000000
--- a/res/drawable-mdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_focused_holo.9.png b/res/drawable-mdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index c9972e7..0000000
--- a/res/drawable-mdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_holo.9.png b/res/drawable-mdpi/tab_selected_holo.9.png
deleted file mode 100644
index 587337c..0000000
--- a/res/drawable-mdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 284f534..0000000
--- a/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 155c4fc..0000000
--- a/res/drawable-mdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index f0cecd1..0000000
--- a/res/drawable-mdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_holo.9.png b/res/drawable-mdpi/tab_unselected_holo.9.png
deleted file mode 100644
index a2dbf42..0000000
--- a/res/drawable-mdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index f1a2819..0000000
--- a/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index b1223fe..0000000
--- a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/hand.png b/res/drawable-xhdpi/hand.png
deleted file mode 100644
index 35b678c..0000000
--- a/res/drawable-xhdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_focused_holo.9.png b/res/drawable-xhdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 03cfb09..0000000
--- a/res/drawable-xhdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_holo.9.png b/res/drawable-xhdpi/tab_selected_holo.9.png
deleted file mode 100644
index e4229f2..0000000
--- a/res/drawable-xhdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 2412711..0000000
--- a/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_pressed_holo.9.png b/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index e862cb1..0000000
--- a/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_focused_holo.9.png b/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index f3a5cbd..0000000
--- a/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_holo.9.png b/res/drawable-xhdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 9465173..0000000
--- a/res/drawable-xhdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index 1653600..0000000
--- a/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png b/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index f1eb673..0000000
--- a/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/hand.png b/res/drawable-xxhdpi/hand.png
deleted file mode 100644
index 88c2a88..0000000
--- a/res/drawable-xxhdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_focused_holo.9.png b/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 2400c65..0000000
--- a/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_holo.9.png b/res/drawable-xxhdpi/tab_selected_holo.9.png
deleted file mode 100644
index 5067cbb..0000000
--- a/res/drawable-xxhdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png b/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 84c246d..0000000
--- a/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png b/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index 939e0c3..0000000
--- a/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_holo.9.png b/res/drawable-xxhdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 62ca6cf..0000000
--- a/res/drawable-xxhdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png b/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index 58ac0d6..0000000
--- a/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/tab_widget_indicator_selector.xml b/res/drawable/tab_widget_indicator_selector.xml
deleted file mode 100644
index d06f757..0000000
--- a/res/drawable/tab_widget_indicator_selector.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- Non focused states -->
-    <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_holo" />
-
-    <!-- Focused states -->
-    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_holo" />
-    <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_holo" />
-
-    <!-- Pressed -->
-    <!--    Non focused states -->
-    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_holo" />
-    <item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
-
-    <!--    Focused states -->
-    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_focused_holo" />
-    <item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_focused_holo" />
-</selector>
diff --git a/res/layout-sw720dp/market_button.xml b/res/layout-sw720dp/market_button.xml
deleted file mode 100644
index 7eaeafa..0000000
--- a/res/layout-sw720dp/market_button.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/MarketButton"
-    android:onClick="onClickAppMarketButton"
-    android:gravity="center"
-    android:paddingLeft="32dp"
-    android:paddingRight="32dp"
-    android:drawablePadding="10dp"
-    android:background="@drawable/tab_widget_indicator_selector"
-    android:text="@string/market"
-    android:contentDescription="@string/market"
-    android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
-    android:textStyle="bold"
-    android:textSize="14sp"
-    android:textAllCaps="true"
-    android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
-    android:shadowDx="0.0"
-    android:shadowDy="0.0"
-    android:shadowRadius="2.0"
-    android:focusable="true"
-    android:clickable="true" />
diff --git a/res/layout/market_button.xml b/res/layout/market_button.xml
deleted file mode 100644
index 41e6ec7..0000000
--- a/res/layout/market_button.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/MarketButton"
-    android:onClick="onClickAppMarketButton"
-    android:gravity="center"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:background="@drawable/tab_widget_indicator_selector"
-    android:contentDescription="@string/market"
-    android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
-    android:shadowDx="0.0"
-    android:shadowDy="0.0"
-    android:shadowRadius="2.0"
-    android:focusable="true"
-    android:clickable="true" />
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 558900c..4b7423e 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!--
+     Copyright (C) 2013 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,47 +14,50 @@
      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="wrap_content"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal|bottom"
-    android:orientation="horizontal">
+    android:gravity="top"
+    android:orientation="horizontal" >
 
     <TextView
         android:id="@+id/wallpaper_button"
-        android:layout_width="wrap_content"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_gravity="start|top"
-        android:text="@string/wallpaper_button_text"
+        android:layout_weight="1"
         android:drawablePadding="4dp"
         android:drawableTop="@drawable/wallpaper_button"
-        android:gravity="center_horizontal"
         android:fontFamily="sans-serif-condensed"
+        android:gravity="center_horizontal"
+        android:text="@string/wallpaper_button_text"
         android:textAllCaps="true"
         android:textSize="12sp" />
+
     <TextView
         android:id="@+id/widget_button"
-        android:layout_width="wrap_content"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal|top"
-        android:text="@string/widget_button_text"
+        android:layout_weight="1"
         android:drawablePadding="4dp"
-        android:gravity="center_horizontal"
         android:drawableTop="@drawable/widget_button"
         android:fontFamily="sans-serif-condensed"
-        android:textAllCaps="true"
-        android:textSize="12sp"/>
-    <TextView
-        android:id="@+id/settings_button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="end|top"
-        android:text="@string/settings_button_text"
-        android:drawablePadding="4dp"
         android:gravity="center_horizontal"
-        android:drawableTop="@drawable/setting_button"
-        android:fontFamily="sans-serif-condensed"
+        android:text="@string/widget_button_text"
         android:textAllCaps="true"
         android:textSize="12sp" />
-</FrameLayout>
+
+    <TextView
+        android:id="@+id/settings_button"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:drawablePadding="4dp"
+        android:drawableTop="@drawable/setting_button"
+        android:fontFamily="sans-serif-condensed"
+        android:gravity="center_horizontal"
+        android:text="@string/settings_button_text"
+        android:textAllCaps="true"
+        android:textSize="12sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/tab_widget_indicator.xml b/res/layout/tab_widget_indicator.xml
deleted file mode 100644
index de7c50e..0000000
--- a/res/layout/tab_widget_indicator.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<com.android.launcher3.AccessibleTabView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/TabIndicator.AppsCustomize" />
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 1c75b5a..9207dde 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Legstukke"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Wys Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Raak en hou om \'n legstuk op te tel."</string>
-    <string name="market" msgid="2619650989819296998">"Winkel"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Kan nie item op hierdie Tuisskerm laat los nie."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Kies legstuk om te skep"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 5938bf0..82765c2 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ፍርግሞች"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ፍርግም ለማንሳት ይንኩ እና ይያዙት"</string>
-    <string name="market" msgid="2619650989819296998">"ግዛ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"ንጥሉን እዚህ የመነሻ ማያ ገጽ ላይ ማኖር አልተቻለም።"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ለመፍጠር መግብር ይምረጡ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 41184a5..5d4ae42 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"الأدوات"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"المس مع الاستمرار لاختيار إحدى الأدوات."</string>
-    <string name="market" msgid="2619650989819296998">"تسوق"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"تعذر إسقاط العنصر على هذه الشاشة الرئيسية."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"اختيار أداة لإنشائها"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 05c5a7d..1bdbb9c 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Приспособления"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Докоснете и задръжте за избор на приспособление."</string>
-    <string name="market" msgid="2619650989819296998">"Пазаруване"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Не можа да се премести на този начален екран."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор на приспособл. за създаване"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 616a316..9cb31d7 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra la memòria"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premut un widget per triar-lo."</string>
-    <string name="market" msgid="2619650989819296998">"Compra"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"No s\'ha pogut deixar anar l\'element a Inici."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Tria el widget que vulguis crear"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 9bce2e3..f5a0554 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobrazit Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget vyberete dotykem a podržením."</string>
-    <string name="market" msgid="2619650989819296998">"Obchod"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Na tuto plochu položku nelze přesunout."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vyberte widget k vytvoření"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 216a01d..a9ded74 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryk på en widget, og hold den nede for at vælge."</string>
-    <string name="market" msgid="2619650989819296998">"Køb i Google Play Butik"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementet kunne ikke trækkes til startskærmen."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vælg den widget, du vil oprette"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index eda4920..5bf1a7c 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Speicher anzeigen"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Zum Hinzufügen Widget berühren und halten"</string>
-    <string name="market" msgid="2619650989819296998">"Einkaufen"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Element wurde nicht auf diesem Startbildschirm abgelegt."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget zum Erstellen auswählen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 4567ea6..4916337 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Γραφικά στοιχεία"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Αγγίξτε παρατεταμένα για να πάρετε ένα γραφ.στοιχ."</string>
-    <string name="market" msgid="2619650989819296998">"Αγορά"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Αδυναμία τοποθέτησης στοιχείου στην Αρχική οθόνη."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Επιλ. γραφ. στοιχείο για δημιουργία"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index bf10a22..53b4620 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
-    <string name="market" msgid="2619650989819296998">"Shop"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index bf10a22..53b4620 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
-    <string name="market" msgid="2619650989819296998">"Shop"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 79eb9a1..dd5575b 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén presionado el widget que desees elegir."</string>
-    <string name="market" msgid="2619650989819296998">"Comprar"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Error al soltar elemento en la pantalla principal"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Elegir los widgets para crear"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 2914482..e66b79e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén pulsado el widget que quieras seleccionar."</string>
-    <string name="market" msgid="2619650989819296998">"Tienda"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Error al arrastrar elemento a pantalla de inicio."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecciona widget a añadir"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 8943b34..bd70aa4 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Vidinad"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mälu kuvamine"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidina valimiseks vajutage ja hoidke seda all."</string>
-    <string name="market" msgid="2619650989819296998">"Pood"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Üksust ei saanud sellele avaekraanile tuua."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valige loomiseks vidin"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 6607843..5b428cc 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ابزارک‌ها"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"‏نمایش Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"برای انتخاب ابزارک لمس کنید و نگه دارید."</string>
-    <string name="market" msgid="2619650989819296998">"فروشگاه"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"این مورد را نمی‌توان در این صفحه اصلی رها کرد."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"انتخاب ابزارکی که باید ایجاد شود"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index eccb06e..63eb3f5 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgetit"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Näytä muisti"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Valitse widget painamalla sitä pitkään."</string>
-    <string name="market" msgid="2619650989819296998">"Kauppa"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Kohteen lisääminen tähän aloitusruutuun epäonnistui."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valitse luotava widget"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index aac11ed..fb78002 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Maintenez un doigt sur le widget pour l\'ajouter."</string>
-    <string name="market" msgid="2619650989819296998">"Magasiner"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Imposs. de déposer l\'élément sur l\'écran d\'accueil"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionnez le widget à créer"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b2eee99..ce657b9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"App. de manière prolongée pour sélectionner widget."</string>
-    <string name="market" msgid="2619650989819296998">"Boutique"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Impossible de déposer élément sur écran d\'accueil."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionner le widget à créer"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index ac0681f..7bf9c85 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -26,11 +26,10 @@
     <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="widgets_tab_label" msgid="2921133187116603919">"विजेट"</string>
-    <string name="widget_adder" msgid="3201040140710381657">"विजेट"</string>
+    <string name="widgets_tab_label" msgid="2921133187116603919">"शॉर्टकट"</string>
+    <string name="widget_adder" msgid="3201040140710381657">"शॉर्टकट"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"मेमोरी दिखाएं"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट को चुनने के लिए स्‍पर्श करके रखें."</string>
-    <string name="market" msgid="2619650989819296998">"खरीदारी करें"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"आइटम को इस होम स्‍क्रीन पर नहीं छोड़ा जा सका."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"बनाने के लिए विजेट चुनें"</string>
@@ -41,7 +40,7 @@
     <string name="menu_item_add_item" msgid="1264911265836810421">"होम स्‍क्रीन में जोड़ें"</string>
     <string name="group_applications" msgid="3797214114206693605">"ऐप्लिकेशन"</string>
     <string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
-    <string name="group_widgets" msgid="1569030723286851002">"विजेट"</string>
+    <string name="group_widgets" msgid="1569030723286851002">"शॉर्टकट"</string>
     <string name="completely_out_of_space" msgid="6106288382070760318">"आपकी होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
     <string name="out_of_space" msgid="4691004494942118364">"इस होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
     <string name="hotseat_out_of_space" msgid="7448809638125333693">"पसंदीदा ट्रे में और स्थान नहीं है"</string>
@@ -86,7 +85,7 @@
     <string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d में से %1$d"</string>
     <string name="workspace_scroll_format" msgid="8458889198184077399">"होम स्क्रीन %2$d में से %1$d"</string>
     <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"ऐप्लिकेशन पृष्ठ %2$d में से %1$d"</string>
-    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"विजेट पृष्ठ %2$d में से %1$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"शॉर्टकट %2$d में से %1$d"</string>
     <string name="first_run_cling_title" msgid="2459738000155917941">"स्वागत है"</string>
     <string name="first_run_cling_description" msgid="6447072552696253358">"जैसा चाहें वैसा उपयोग करें."</string>
     <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
@@ -97,8 +96,8 @@
     <string name="migration_cling_copy_apps" msgid="946331230090919440">"आइकन की प्रतिलिपि बनाएं"</string>
     <string name="migration_cling_use_default" msgid="2626475813981258626">"फिर से शुरू करें"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"अपने स्थान को व्यवस्थित करें"</string>
-    <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, विजेट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
-    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, विजेट और सेटिंग"</string>
+    <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, शॉर्टकट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, शॉर्टकट और सेटिंग"</string>
     <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"पृष्ठभूमि कस्टमाइज़ करने के लिए स्पर्श करके रखें"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"समझ लिया"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"यहां एक फ़ोल्डर है"</string>
@@ -110,7 +109,7 @@
     <string name="folder_closed" msgid="4100806530910930934">"फ़ोल्डर बंद किया गया"</string>
     <string name="folder_renamed" msgid="1794088362165669656">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
     <string name="folder_name_format" msgid="6629239338071103179">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
+    <string name="widget_button_text" msgid="2880537293434387943">"शॉर्टकट"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
     <string name="settings_button_text" msgid="8119458837558863227">"सेटिंग"</string>
     <string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षा में"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 6e69684..62c1916 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Prikaži mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite i držite kako biste podigli widget."</string>
-    <string name="market" msgid="2619650989819296998">"Kupi"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Stavka nije ispuštena na ovaj početni zaslon."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Odabir widgeta za stvaranje"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 1c11865..0dcd5df 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Modulok"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem. megjelenítése"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Modul felvételéhez érintse meg, és tartsa lenyomva"</string>
-    <string name="market" msgid="2619650989819296998">"Vásárlás"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Nem lehet elemeket dobni erre a kezdőképernyőre."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"A létrehozáshoz válasszon modult"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index be5568c..bae306d 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Հպեք և պահեք՝ վիջեթն ընտրելու համար:"</string>
-    <string name="market" msgid="2619650989819296998">"Խանութ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Հնարավոր չէ տեղադրել տարրն այս հիմնական էկրանին:"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ստեղծելու համար ընտրեք վիջեթը"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0aadeb3..b8f6d96 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Tampilkan Memori"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh lama untuk memilih widget."</string>
-    <string name="market" msgid="2619650989819296998">"Belanja"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepas item ke layar Utama ini."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget untuk membuat"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 77242dd..7cd03a8 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Tocca e tieni premuto per scegliere un widget."</string>
-    <string name="market" msgid="2619650989819296998">"Acquista"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Rilascio elemento in schermata Home non riuscito."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Scegli il widget da creare"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 02012ce..44dfac7 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"רכיבי ווידג\'ט"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"גע נגיעה רציפה בווידג\'ט כדי לבחור בו."</string>
-    <string name="market" msgid="2619650989819296998">"קנה"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"לא ניתן היה לשחרר את הפריט במסך דף הבית הזה."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"בחר ווידג\'ט ליצירה"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 3ce781b..e52a4ab 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ウィジェット"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ウィジェットを追加するには押し続けます。"</string>
-    <string name="market" msgid="2619650989819296998">"ショップ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"このホーム画面にアイテムをドロップできませんでした"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"作成するウィジェットの選択"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 31cdb40..5ac936c 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"შეეხეთ და დააყოვნეთ ვიჯეტის ასარჩევად."</string>
-    <string name="market" msgid="2619650989819296998">"მაღაზია"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"ერთეულის მთავარ ეკრანზე ჩაგდება ვერ მოხერხდა."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"აირჩიეთ ვიჯეტი შესაქმნელად"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 19dd31e..0aec2b0 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ធាតុ​ក្រាហ្វិក"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ​ Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ប៉ះ &amp; សង្កត់ ដើម្បី​ជ្រើស​ធាតុ​ក្រាហ្វិក។"</string>
-    <string name="market" msgid="2619650989819296998">"ហាងទំនិញ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"មិន​អាច​ទម្លាក់​ធាតុ​លើ​អេក្រង់​ដើម​នេះ​ទេ"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ជ្រើស​ធាតុ​ក្រាហ្វិក ដើម្បី​​​បង្កើត"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 88ea54e..88c4ded 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"위젯"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"위젯을 선택하려면 길게 터치하세요."</string>
-    <string name="market" msgid="2619650989819296998">"쇼핑하기"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"홈 화면에 항목을 놓을 수 없습니다."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"만들 위젯 선택"</string>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 87a7444..ac210d7 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -40,9 +40,5 @@
         <item name="android:shadowRadius">4.0</item>
     </style>
 
-<!-- AppsCustomize -->
-    <style name="TabIndicator.AppsCustomize">
-        <item name="android:maxWidth">200dp</item>
-    </style>
 </resources>
 
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index b30a69d..41e41ce 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"ສຳພັດຄ້າງໄວ້ ເພື່ອຈັບວິດເຈັດ."</string>
-    <string name="market" msgid="2619650989819296998">"ຮ້ານຄ້າ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"ບໍ່ສາມາດວາງລາຍການໃສ່ໜ້າຈໍຫຼັກນີ້ໄດ້"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ເລືອກວິດເຈັດເພື່ອສ້າງມັນ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 72b029c..145b700 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Valdikliai"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rodyti atmintinę"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Palieskite ir laikykite, kad pasirinkt. valdiklį."</string>
-    <string name="market" msgid="2619650989819296998">"Apsipirkti"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Nepavyko nuvilkti elemento į šį pagrindinį ekraną."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pasirinkite norimą kurti valdiklį"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 280bc0c..af591e0 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Logrīki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rādīt atmiņu"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Lai izvēlētos logrīku, pieskarieties un turiet to."</string>
-    <string name="market" msgid="2619650989819296998">"Iepirkties"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Nevarēja nomest vienumu šajā sākuma ekrānā."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izveidojamā logrīka izvēle"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index 816803a..faa5276 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Виджет"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетийг авах бол хүрээд барина уу."</string>
-    <string name="market" msgid="2619650989819296998">"Дэлгүүр"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Энэ Нүүр дэлгэцэнд буулгах боломжгүй."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Үүсгэх виджетээ сонгоно уу"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 07236d65..d80feb9 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -24,14 +24,12 @@
     <string name="uid_name" msgid="7820867637514617527">"Apl Teras Android"</string>
     <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
-    <!-- no translation found for activity_not_available (7456344436509528827) -->
-    <skip />
+    <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>
     <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>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh &amp; tahan untuk mengambil widget."</string>
-    <string name="market" msgid="2619650989819296998">"Beli-belah"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepaskan item pada Skrin Utama."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget yang hendak dibuat"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 13d8843..d0580a7 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Moduler"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis minne"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Trykk og hold inne for å plukke opp en modul."</string>
-    <string name="market" msgid="2619650989819296998">"Butikk"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Kunne ikke slippe elementet på denne startsiden."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Velg modul for oppretting"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index c9f7e67..be588b2 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Geheugen weergeven"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Blijf aanraken om een widget toe te voegen."</string>
-    <string name="market" msgid="2619650989819296998">"Winkelen"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Kan item niet neerzetten in dit startscherm."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget selecteren om te maken"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 44e46e0..793a371 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widżety"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaż pamięć"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Aby dodać widżet, kliknij go i przytrzymaj."</string>
-    <string name="market" msgid="2619650989819296998">"Sklep"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Nie można upuścić elementu na tym ekranie głównym."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Wybierz widżet, który chcesz dodać"</string>
diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
deleted file mode 100644
index ab6a1eb..0000000
--- a/res/values-port/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-
-<resources>
-<!-- AppsCustomize -->
-    <style name="TabIndicator.AppsCustomize">
-        <item name="android:maxWidth">130dp</item>
-    </style>
-</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index fb33678..11acb47 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Prima sem soltar para escolher um widget."</string>
-    <string name="market" msgid="2619650989819296998">"Comprar"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível largar o item neste Ecrã Principal."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Escolher um widget para criar"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 2f86d0b..64b9bb1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memória"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Toque e pressione para selecionar um widget."</string>
-    <string name="market" msgid="2619650989819296998">"Comprar"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível soltar o item nesta tela inicial."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecione um widget para criar"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index c6000ee..4e36a66 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgeturi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afișați memoria"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Atingeți lung un widget pentru a-l alege."</string>
-    <string name="market" msgid="2619650989819296998">"Cumpărați"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Nu se poate plasa articolul pe ecranul de pornire."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Alegeți widgetul de creat"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 134582d..c0ee48c 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Чтобы выбрать виджет, нажмите на значок и удерживайте его."</string>
-    <string name="market" msgid="2619650989819296998">"Google Play"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Не удалось добавить элемент на главный экран"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Выберите виджет"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index d80b5ac..e984278 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Miniaplikácie"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobraziť pamäť"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Miniaplikáciu pridáte stlačením a podržaním."</string>
-    <string name="market" msgid="2619650989819296998">"Obchod"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Položku sa nepodarilo presunúť na túto plochu."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Zvoľte miniaplikáciu na vytvorenie"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 882ddb4..8047791 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Pripomočki"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaži pomnilnik"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Za izbiro pripomočka se ga dotaknite in pridržite."</string>
-    <string name="market" msgid="2619650989819296998">"Nakup"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementa ni mogoče spustiti na začetni zaslon."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izberite pripomoček za ustvarjanje"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 63f48f5..31430fe 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Додирните и задржите да бисте изабрали виџет."</string>
-    <string name="market" msgid="2619650989819296998">"Купујте"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Није могуће отпустити ставку на почетни екран."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор виџета за прављење"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 674f1df..7f2af8a 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widgetar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Visa Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryck länge om du vill flytta en widget."</string>
-    <string name="market" msgid="2619650989819296998">"Butik"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Objektet kunde inte släppas på startskärmen."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ange vilken widget du vill använda"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 94f53ce..485157b 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Wijeti"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Onyesha Kumbukumbu"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Gusa na ushikilie ili kuteua wijeti."</string>
-    <string name="market" msgid="2619650989819296998">"Nunua"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Haikuweza kudondosha kipengee kwenye skrini hii ya Kwanza."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chagua wijeti ili uunde"</string>
diff --git a/res/values-sw340dp-port/styles.xml b/res/values-sw340dp-port/styles.xml
index 24f4ba2..8ac3b5e 100644
--- a/res/values-sw340dp-port/styles.xml
+++ b/res/values-sw340dp-port/styles.xml
@@ -24,9 +24,4 @@
         <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
         <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
     </style>
-
-<!-- AppsCustomize -->
-    <style name="TabIndicator.AppsCustomize">
-        <item name="android:maxWidth">150dp</item>
-    </style>
 </resources>
diff --git a/res/values-sw720dp-port/styles.xml b/res/values-sw720dp-port/styles.xml
deleted file mode 100644
index 57f07ac..0000000
--- a/res/values-sw720dp-port/styles.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-
-<resources>
-    <style name="TabIndicator.AppsCustomize">
-        <item name="android:maxWidth">180dp</item>
-    </style>
-</resources>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index 71f0304..4ec04d9 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -19,13 +19,6 @@
 
 <resources>
 <!-- Workspace -->
-    <style name="TabIndicator.AppsCustomize">
-        <item name="android:paddingLeft">32dp</item>
-        <item name="android:paddingRight">32dp</item>
-        <item name="android:textSize">14sp</item>
-        <item name="android:maxWidth">240dp</item>
-    </style>
-
     <style name="SearchButton">
     </style>
     <style name="DropTargetButtonContainer">
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 06ed6ec..26c72f4 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"วิดเจ็ต"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"แตะค้างเพื่อรับวิดเจ็ต"</string>
-    <string name="market" msgid="2619650989819296998">"เลือกซื้อ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"ไม่สามารถวางรายการลงในหน้าจอหลักนี้"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"เลือกวิดเจ็ตที่จะสร้าง"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 3c877d0..27481be 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Mga Widget"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ipakita ang Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Pindutin nang matagal upang kumuha ng widget."</string>
-    <string name="market" msgid="2619650989819296998">"Mamili"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Hindi ma-drop ang item sa Home screen na ito."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pumili ng widget na gagawin"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 2f67ad2..3bea496 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Widget\'lar"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Belleği Göster"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget seçmek için dokunun ve basılı tutun."</string>
-    <string name="market" msgid="2619650989819296998">"Mağaza"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Öğe bu Ana ekrana bırakılamadı."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Oluşturmak için widget seçin"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 12c9dd4..86ca01b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Віджети"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Натисніть і утримуйте, щоб вибрати віджет."</string>
-    <string name="market" msgid="2619650989819296998">"Магазин"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Не вдалося додати елемент на цей головний екран."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Вибрати віджет для створення"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 79db2c5..b8d0063 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Tiện ích con"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Hiển thị bộ nhớ"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Chạm và giữ để chọn tiện ích con."</string>
-    <string name="market" msgid="2619650989819296998">"Mua"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Không thể thả mục vào Màn hình chính này."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chọn tiện ích con để tạo"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 37923dd..a098235 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"触摸并按住小部件即可选择。"</string>
-    <string name="market" msgid="2619650989819296998">"商店"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"无法将相关内容拖放到此主屏幕上。"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"选择要创建的小部件"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 346e60a..796c72e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
-    <string name="market" msgid="2619650989819296998">"商店"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至主畫面。"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a63fb69..ff3fa8c 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
-    <string name="market" msgid="2619650989819296998">"購物"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至這個主螢幕上。"</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index f94b166..891f672 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -30,7 +30,6 @@
     <string name="widget_adder" msgid="3201040140710381657">"Amawijethi"</string>
     <string name="toggle_weight_watcher" msgid="5645299835184636119">"Bonisa i-Mem"</string>
     <string name="long_press_widget_to_add" msgid="7699152356777458215">"Thinta uphinde ubambe ukuze uphakamise iwijethi."</string>
-    <string name="market" msgid="2619650989819296998">"Thenga"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="external_drop_widget_error" msgid="3165821058322217155">"Ayikwazanga ukwehlisela into kulesi sikrini se-Ikhaya."</string>
     <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Khetha iwijethi ongayidala"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 65f8f22..b4e1543 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -130,12 +130,14 @@
         <attr name="title" format="reference" />
         <attr name="uri" format="string" />
     </declare-styleable>
+
     <declare-styleable name="Extra">
         <attr name="key" format="string" />
         <attr name="value" format="string" />
     </declare-styleable>
     <declare-styleable name="Include">
         <attr name="workspace" format="reference" />
+        <attr name="folderItems" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="PreloadIconDrawable">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 29837ea..2daf9fe 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -29,8 +29,6 @@
 
     <color name="appwidget_error_color">#FCCC</color>
 
-    <color name="workspace_all_apps_and_delete_zone_text_color">#CCFFFFFF</color>
-    <color name="workspace_all_apps_and_delete_zone_text_shadow_color">#A0000000</color>
     <color name="workspace_icon_text_color">#FFF</color>
 
     <color name="quantum_panel_text_color">#FF666666</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dd9b170..a6397e3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -44,6 +44,8 @@
     <string name="activity_not_available">App isn\'t available</string>
     <!-- SafeMode shortcut error string -->
     <string name="safemode_shortcut_error">Downloaded app disabled in Safe mode</string>
+    <!-- SafeMode widget error string -->
+    <string name="safemode_widget_error">Widgets disabled in Safe mode</string>
     <!--  Labels for the tabs in the customize drawer -->
     <string name="widgets_tab_label">Widgets</string>
 
@@ -54,9 +56,6 @@
     <!-- AppsCustomize pane -->
     <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
     <string name="long_press_widget_to_add">Touch &amp; hold to pick up a widget.</string>
-    <!-- Market button text.  The market button text is removed in Launcher.java 
-         in the Phone UI. [CHAR LIMIT=32] -->
-    <string name="market">Shop</string>
     <!-- The format string for the dimensions of a widget in the drawer -->
     <!-- There is a special version of this format string for Farsi -->
     <string name="widget_dims_format">%1$d \u00d7 %2$d</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 56a205f..873b74c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -78,35 +78,6 @@
         <item name="android:shadowRadius">4.0</item>
     </style>
 
-    <style name="TabIndicator">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">20dp</item>
-        <item name="android:paddingRight">20dp</item>
-        <item name="android:background">@drawable/tab_widget_indicator_selector</item>
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
-        <item name="android:textSize">12sp</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:ellipsize">end</item>
-    </style>
-    <style name="TabIndicator.AppsCustomize">
-        <!-- Overridden in values-land -->
-    </style>
-
-    <style name="MarketButton">
-        <item name="android:paddingLeft">5dp</item>
-        <item name="android:paddingRight">5dp</item>
-        <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
-        <item name="android:textSize">18sp</item>
-        <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
-        <item name="android:shadowDx">0.0</item>
-        <item name="android:shadowDy">0.0</item>
-        <item name="android:shadowRadius">2.0</item>
-    </style>
-
     <style name="PreloadIcon">
         <item name="background">@drawable/virtual_preload</item>
         <item name="indicatorSize">4dp</item>
diff --git a/res/xml/default_workspace_4x4_no_all_apps.xml b/res/xml/default_workspace_4x4_no_all_apps.xml
deleted file mode 100644
index 7e1301c..0000000
--- a/res/xml/default_workspace_4x4_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
-    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <!-- Dialer Hangouts Maps Chrome Camera -->
-    <favorite
-        launcher:packageName="com.google.android.dialer"
-        launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
-        launcher:container="-101"
-        launcher:screen="0"
-        launcher:x="0"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.talk"
-        launcher:className="com.google.android.talk.SigningInActivity"
-        launcher:container="-101"
-        launcher:screen="1"
-        launcher:x="1"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.apps.maps"
-        launcher:className="com.google.android.maps.MapsActivity"
-        launcher:container="-101"
-        launcher:screen="2"
-        launcher:x="2"
-        launcher:y="0"/>
-    <favorite
-        launcher:packageName="com.android.chrome"
-        launcher:className="com.google.android.apps.chrome.Main"
-        launcher:container="-101"
-        launcher:screen="3"
-        launcher:x="3"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.GoogleCamera"
-        launcher:className="com.android.camera.CameraLauncher"
-        launcher:container="-101"
-        launcher:screen="4"
-        launcher:x="4"
-        launcher:y="0" />
-</favorites>
-
diff --git a/res/xml/default_workspace_5x5_no_all_apps.xml b/res/xml/default_workspace_5x5_no_all_apps.xml
deleted file mode 100644
index f54a204..0000000
--- a/res/xml/default_workspace_5x5_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
-    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <!-- Dialer Hangouts Maps Chrome Camera -->
-    <favorite
-        launcher:packageName="com.google.android.dialer"
-        launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
-        launcher:container="-101"
-        launcher:screen="1"
-        launcher:x="1"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.talk"
-        launcher:className="com.google.android.talk.SigningInActivity"
-        launcher:container="-101"
-        launcher:screen="2"
-        launcher:x="2"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.apps.maps"
-        launcher:className="com.google.android.maps.MapsActivity"
-        launcher:container="-101"
-        launcher:screen="3"
-        launcher:x="3"
-        launcher:y="0"/>
-    <favorite
-        launcher:packageName="com.android.chrome"
-        launcher:className="com.google.android.apps.chrome.Main"
-        launcher:container="-101"
-        launcher:screen="4"
-        launcher:x="4"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.GoogleCamera"
-        launcher:className="com.android.camera.CameraLauncher"
-        launcher:container="-101"
-        launcher:screen="5"
-        launcher:x="5"
-        launcher:y="0" />
-</favorites>
-
diff --git a/res/xml/default_workspace_5x6_no_all_apps.xml b/res/xml/default_workspace_5x6_no_all_apps.xml
deleted file mode 100644
index f54a204..0000000
--- a/res/xml/default_workspace_5x6_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
-    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <!-- Dialer Hangouts Maps Chrome Camera -->
-    <favorite
-        launcher:packageName="com.google.android.dialer"
-        launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
-        launcher:container="-101"
-        launcher:screen="1"
-        launcher:x="1"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.talk"
-        launcher:className="com.google.android.talk.SigningInActivity"
-        launcher:container="-101"
-        launcher:screen="2"
-        launcher:x="2"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.apps.maps"
-        launcher:className="com.google.android.maps.MapsActivity"
-        launcher:container="-101"
-        launcher:screen="3"
-        launcher:x="3"
-        launcher:y="0"/>
-    <favorite
-        launcher:packageName="com.android.chrome"
-        launcher:className="com.google.android.apps.chrome.Main"
-        launcher:container="-101"
-        launcher:screen="4"
-        launcher:x="4"
-        launcher:y="0" />
-    <favorite
-        launcher:packageName="com.google.android.GoogleCamera"
-        launcher:className="com.android.camera.CameraLauncher"
-        launcher:container="-101"
-        launcher:screen="5"
-        launcher:x="5"
-        launcher:y="0" />
-</favorites>
-
diff --git a/src/com/android/launcher3/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/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 08ed89b..a5d2228 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -36,7 +36,6 @@
 import android.util.Patterns;
 
 import com.android.launcher3.LauncherProvider.SqlArguments;
-import com.android.launcher3.LauncherProvider.WorkspaceLoader;
 import com.android.launcher3.LauncherSettings.Favorites;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -47,13 +46,11 @@
 import java.util.HashMap;
 
 /**
- * This class contains contains duplication of functionality as found in
- * LauncherProvider#DatabaseHelper. It has been isolated and differentiated in order
- * to cleanly and separately represent AutoInstall default layout format and policy.
+ * Layout parsing code for auto installs layout
  */
-public class AutoInstallsLayout implements WorkspaceLoader {
+public class AutoInstallsLayout {
     private static final String TAG = "AutoInstalls";
-    private static final boolean LOGD = true;
+    private static final boolean LOGD = false;
 
     /** Marker action used to discover a package which defines launcher customization */
     static final String ACTION_LAUNCHER_CUSTOMIZATION =
@@ -76,7 +73,8 @@
             Log.e(TAG, "Layout definition not found in package: " + pkg);
             return null;
         }
-        return new AutoInstallsLayout(context, appWidgetHost, callback, pkg, res, layoutId);
+        return new AutoInstallsLayout(context, appWidgetHost, callback, res, layoutId,
+                TAG_WORKSPACE);
     }
 
     // Object Tags
@@ -116,45 +114,55 @@
     private final AppWidgetHost mAppWidgetHost;
     private final LayoutParserCallback mCallback;
 
-    private final PackageManager mPackageManager;
+    protected final PackageManager mPackageManager;
+    protected final Resources mSourceRes;
+    protected final int mLayoutId;
+
+    private final int mHotseatAllAppsRank;
+
+    private final long[] mTemp = new long[2];
     private final ContentValues mValues;
+    private final String mRootTag;
 
-    private final Resources mRes;
-    private final int mLayoutId;
-
-    private SQLiteDatabase mDb;
+    protected SQLiteDatabase mDb;
 
     public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
-            LayoutParserCallback callback, String packageName, Resources res, int layoutId) {
+            LayoutParserCallback callback, Resources res,
+            int layoutId, String rootTag) {
         mContext = context;
         mAppWidgetHost = appWidgetHost;
         mCallback = callback;
 
         mPackageManager = context.getPackageManager();
         mValues = new ContentValues();
+        mRootTag = rootTag;
 
-        mRes = res;
+        mSourceRes = res;
         mLayoutId = layoutId;
+        mHotseatAllAppsRank = LauncherAppState.getInstance()
+                .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
     }
 
-    @Override
+    /**
+     * Loads the layout in the db and returns the number of entries added on the desktop.
+     */
     public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
         mDb = db;
         try {
-            return parseLayout(mRes, mLayoutId, screenIds);
+            return parseLayout(mLayoutId, screenIds);
         } catch (Exception e) {
             Log.w(TAG, "Got exception parsing layout.", e);
             return -1;
         }
     }
 
-    private int parseLayout(Resources res, int layoutId, ArrayList<Long> screenIds)
+    /**
+     * Parses the layout and returns the number of elements added on the homescreen.
+     */
+    protected int parseLayout(int layoutId, ArrayList<Long> screenIds)
             throws XmlPullParserException, IOException {
-        final int hotseatAllAppsRank = LauncherAppState.getInstance()
-                .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
-
-        XmlResourceParser parser = res.getXml(layoutId);
-        beginDocument(parser, TAG_WORKSPACE);
+        XmlResourceParser parser = mSourceRes.getXml(layoutId);
+        beginDocument(parser, mRootTag);
         final int depth = parser.getDepth();
         int type;
         HashMap<String, TagParser> tagParserMap = getLayoutElementsMap();
@@ -165,47 +173,62 @@
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
-
-            mValues.clear();
-            final int container;
-            final long screenId;
-
-            if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) {
-                container = Favorites.CONTAINER_HOTSEAT;
-
-                // Hack: hotseat items are stored using screen ids
-                long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK));
-                screenId = (rank < hotseatAllAppsRank) ? rank : (rank + 1);
-
-            } else {
-                container = Favorites.CONTAINER_DESKTOP;
-                screenId = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
-
-                mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
-                mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
-            }
-
-            mValues.put(Favorites.CONTAINER, container);
-            mValues.put(Favorites.SCREEN, screenId);
-
-            TagParser tagParser = tagParserMap.get(parser.getName());
-            if (tagParser == null) {
-                if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
-                continue;
-            }
-            long newElementId = tagParser.parseAndAdd(parser, res);
-            if (newElementId >= 0) {
-                // Keep track of the set of screens which need to be added to the db.
-                if (!screenIds.contains(screenId) &&
-                        container == Favorites.CONTAINER_DESKTOP) {
-                    screenIds.add(screenId);
-                }
-                count++;
-            }
+            count += parseAndAddNode(parser, tagParserMap, screenIds);
         }
         return count;
     }
 
+    /**
+     * Parses container and screenId attribute from the current tag, and puts it in the out.
+     * @param out array of size 2.
+     */
+    protected void parseContainerAndScreen(XmlResourceParser parser, long[] out) {
+        if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) {
+            out[0] = Favorites.CONTAINER_HOTSEAT;
+            // Hack: hotseat items are stored using screen ids
+            long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK));
+            out[1] = (rank < mHotseatAllAppsRank) ? rank : (rank + 1);
+        } else {
+            out[0] = Favorites.CONTAINER_DESKTOP;
+            out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
+        }
+    }
+
+    /**
+     * Parses the current node and returns the number of elements added.
+     */
+    protected int parseAndAddNode(
+            XmlResourceParser parser,
+            HashMap<String, TagParser> tagParserMap,
+            ArrayList<Long> screenIds)
+                    throws XmlPullParserException, IOException {
+        mValues.clear();
+        parseContainerAndScreen(parser, mTemp);
+        final long container = mTemp[0];
+        final long screenId = mTemp[1];
+
+        mValues.put(Favorites.CONTAINER, container);
+        mValues.put(Favorites.SCREEN, screenId);
+        mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
+        mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
+
+        TagParser tagParser = tagParserMap.get(parser.getName());
+        if (tagParser == null) {
+            if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
+            return 0;
+        }
+        long newElementId = tagParser.parseAndAdd(parser);
+        if (newElementId >= 0) {
+            // Keep track of the set of screens which need to be added to the db.
+            if (!screenIds.contains(screenId) &&
+                    container == Favorites.CONTAINER_DESKTOP) {
+                screenIds.add(screenId);
+            }
+            return 1;
+        }
+        return 0;
+    }
+
     protected long addShortcut(String title, Intent intent, int type) {
         long id = mCallback.generateNewItemId();
         mValues.put(Favorites.INTENT, intent.toUri(0));
@@ -225,7 +248,7 @@
         HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
         parsers.put(TAG_APP_ICON, new AppShortcutParser());
         parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
-        parsers.put(TAG_SHORTCUT, new ShortcutParser());
+        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
         return parsers;
     }
 
@@ -235,23 +258,26 @@
         parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
         parsers.put(TAG_FOLDER, new FolderParser());
         parsers.put(TAG_APPWIDGET, new AppWidgetParser());
-        parsers.put(TAG_SHORTCUT, new ShortcutParser());
+        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
         return parsers;
     }
 
-    private interface TagParser {
+    protected interface TagParser {
         /**
          * Parses the tag and adds to the db
          * @return the id of the row added or -1;
          */
-        long parseAndAdd(XmlResourceParser parser, Resources res)
+        long parseAndAdd(XmlResourceParser parser)
                 throws XmlPullParserException, IOException;
     }
 
-    private class AppShortcutParser implements TagParser {
+    /**
+     * App shortcuts: required attributes packageName and className
+     */
+    protected class AppShortcutParser implements TagParser {
 
         @Override
-        public long parseAndAdd(XmlResourceParser parser, Resources res) {
+        public long parseAndAdd(XmlResourceParser parser) {
             final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
             final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
 
@@ -277,20 +303,30 @@
                     return addShortcut(info.loadLabel(mPackageManager).toString(),
                             intent, Favorites.ITEM_TYPE_APPLICATION);
                 } catch (PackageManager.NameNotFoundException e) {
-                    Log.w(TAG, "Unable to add favorite: " + packageName + "/" + className, e);
+                    if (LOGD) Log.w(TAG, "Unable to add favorite: " + packageName + "/" + className, e);
                 }
                 return -1;
             } else {
-                if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component or uri");
-                return -1;
+                return invalidPackageOrClass(parser);
             }
         }
+
+        /**
+         * Helper method to allow extending the parser capabilities
+         */
+        protected long invalidPackageOrClass(XmlResourceParser parser) {
+            if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component");
+            return -1;
+        }
     }
 
-    private class AutoInstallParser implements TagParser {
+    /**
+     * AutoInstall: required attributes packageName and className
+     */
+    protected class AutoInstallParser implements TagParser {
 
         @Override
-        public long parseAndAdd(XmlResourceParser parser, Resources res) {
+        public long parseAndAdd(XmlResourceParser parser) {
             final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
             final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
             if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
@@ -309,11 +345,19 @@
         }
     }
 
-    private class ShortcutParser implements TagParser {
+    /**
+     * Parses a web shortcut. Required attributes url, icon, title
+     */
+    protected class ShortcutParser implements TagParser {
+
+        private final Resources mIconRes;
+
+        public ShortcutParser(Resources iconRes) {
+            mIconRes = iconRes;
+        }
 
         @Override
-        public long parseAndAdd(XmlResourceParser parser, Resources res) {
-            final String url = getAttributeValue(parser, ATTR_URL);
+        public long parseAndAdd(XmlResourceParser parser) {
             final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
             final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0);
 
@@ -322,29 +366,46 @@
                 return -1;
             }
 
-            if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
-                if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
+            final Intent intent = parseIntent(parser);
+            if (intent == null) {
                 return -1;
             }
-            Drawable icon = res.getDrawable(iconId);
+
+            Drawable icon = mIconRes.getDrawable(iconId);
             if (icon == null) {
                 if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon");
                 return -1;
             }
 
             ItemInfo.writeBitmap(mValues, Utilities.createIconBitmap(icon, mContext));
-            final Intent intent = new Intent(Intent.ACTION_VIEW, null)
-                .setData(Uri.parse(url))
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+            mValues.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
+            mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
+            mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
+
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                         Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-            return addShortcut(res.getString(titleResId), intent, Favorites.ITEM_TYPE_SHORTCUT);
+            return addShortcut(mSourceRes.getString(titleResId),
+                    intent, Favorites.ITEM_TYPE_SHORTCUT);
+        }
+
+        protected Intent parseIntent(XmlResourceParser parser) {
+            final String url = getAttributeValue(parser, ATTR_URL);
+            if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
+                if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
+                return null;
+            }
+            return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url));
         }
     }
 
-    private class AppWidgetParser implements TagParser {
+    /**
+     * AppWidget parser: Required attributes packageName, className, spanX and spanY.
+     * Options child nodes: <extra key=... value=... />
+     */
+    protected class AppWidgetParser implements TagParser {
 
         @Override
-        public long parseAndAdd(XmlResourceParser parser, Resources res)
+        public long parseAndAdd(XmlResourceParser parser)
                 throws XmlPullParserException, IOException {
             final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
             final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
@@ -429,16 +490,24 @@
         }
     }
 
-    private class FolderParser implements TagParser {
-        private final HashMap<String, TagParser> mFolderElements = getFolderElementsMap();
+    protected class FolderParser implements TagParser {
+        private final HashMap<String, TagParser> mFolderElements;
+
+        public FolderParser() {
+            this(getFolderElementsMap());
+        }
+
+        public FolderParser(HashMap<String, TagParser> elements) {
+            mFolderElements = elements;
+        }
 
         @Override
-        public long parseAndAdd(XmlResourceParser parser, Resources res)
+        public long parseAndAdd(XmlResourceParser parser)
                 throws XmlPullParserException, IOException {
             final String title;
             final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
             if (titleResId != 0) {
-                title = res.getString(titleResId);
+                title = mSourceRes.getString(titleResId);
             } else {
                 title = mContext.getResources().getString(R.string.folder_name);
             }
@@ -469,7 +538,7 @@
 
                 TagParser tagParser = mFolderElements.get(parser.getName());
                 if (tagParser != null) {
-                    final long id = tagParser.parseAndAdd(parser, res);
+                    final long id = tagParser.parseAndAdd(parser);
                     if (id >= 0) {
                         folderItems.add(id);
                     }
@@ -508,7 +577,7 @@
         }
     }
 
-    private static final void beginDocument(XmlPullParser parser, String firstElementName)
+    protected static final void beginDocument(XmlPullParser parser, String firstElementName)
             throws XmlPullParserException, IOException {
         int type;
         while ((type = parser.next()) != XmlPullParser.START_TAG
@@ -528,7 +597,7 @@
      * Return attribute value, attempting launcher-specific namespace first
      * before falling back to anonymous attribute.
      */
-    private static String getAttributeValue(XmlResourceParser parser, String attribute) {
+    protected static String getAttributeValue(XmlResourceParser parser, String attribute) {
         String value = parser.getAttributeValue(
                 "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
         if (value == null) {
@@ -541,7 +610,7 @@
      * Return attribute resource value, attempting launcher-specific namespace
      * first before falling back to anonymous attribute.
      */
-    private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
+    protected static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
             int defaultValue) {
         int value = parser.getAttributeResourceValue(
                 "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
new file mode 100644
index 0000000..e3ea40e
--- /dev/null
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -0,0 +1,290 @@
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetHost;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Implements the layout parser with rules for internal layouts and partner layouts.
+ */
+public class DefaultLayoutParser extends AutoInstallsLayout {
+    private static final String TAG = "DefaultLayoutParser";
+
+    private static final String TAG_RESOLVE = "resolve";
+    private static final String TAG_FAVORITES = "favorites";
+    private static final String TAG_FAVORITE = "favorite";
+    private static final String TAG_APPWIDGET = "appwidget";
+    private static final String TAG_SHORTCUT = "shortcut";
+    private static final String TAG_FOLDER = "folder";
+    private static final String TAG_PARTNER_FOLDER = "partner-folder";
+    private static final String TAG_INCLUDE = "include";
+
+    private static final String ATTR_URI = "uri";
+    private static final String ATTR_WORKSPACE = "workspace";
+    private static final String ATTR_CONTAINER = "container";
+    private static final String ATTR_SCREEN = "screen";
+    private static final String ATTR_FOLDER_ITEMS = "folderItems";
+
+    public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
+            LayoutParserCallback callback, Resources sourceRes, int layoutId) {
+        super(context, appWidgetHost, callback, sourceRes, layoutId, TAG_FAVORITES);
+        Log.e(TAG, "Default layout parser initialized");
+    }
+
+    @Override
+    protected HashMap<String, TagParser> getFolderElementsMap() {
+        return getFolderElementsMap(mSourceRes);
+    }
+
+    private HashMap<String, TagParser> getFolderElementsMap(Resources res) {
+        HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+        parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
+        parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
+        return parsers;
+    }
+
+    @Override
+    protected HashMap<String, TagParser> getLayoutElementsMap() {
+        HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+        parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
+        parsers.put(TAG_APPWIDGET, new AppWidgetParser());
+        parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
+        parsers.put(TAG_RESOLVE, new ResolveParser());
+        parsers.put(TAG_FOLDER, new MyFolderParser());
+        parsers.put(TAG_PARTNER_FOLDER, new PartnerFolderParser());
+        return parsers;
+    }
+
+    @Override
+    protected void parseContainerAndScreen(XmlResourceParser parser, long[] out) {
+        out[0] = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+        String strContainer = getAttributeValue(parser, ATTR_CONTAINER);
+        if (strContainer != null) {
+            out[0] = Long.valueOf(strContainer);
+        }
+        out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
+    }
+
+    @Override
+    protected int parseAndAddNode(
+            XmlResourceParser parser,
+            HashMap<String, TagParser> tagParserMap,
+            ArrayList<Long> screenIds)
+                    throws XmlPullParserException, IOException {
+        if (TAG_INCLUDE.equals(parser.getName())) {
+            final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
+            if (resId != 0) {
+                // recursively load some more favorites, why not?
+                return parseLayout(resId, screenIds);
+            } else {
+                return 0;
+            }
+        } else {
+            return super.parseAndAddNode(parser, tagParserMap, screenIds);
+        }
+    }
+
+    /**
+     * AppShortcutParser which also supports adding URI based intents
+     */
+    private class AppShortcutWithUriParser extends AppShortcutParser {
+
+        @Override
+        protected long invalidPackageOrClass(XmlResourceParser parser) {
+            final String uri = getAttributeValue(parser, ATTR_URI);
+            if (TextUtils.isEmpty(uri)) {
+                Log.e(TAG, "Skipping invalid <favorite> with no component or uri");
+                return -1;
+            }
+
+            final Intent metaIntent;
+            try {
+                metaIntent = Intent.parseUri(uri, 0);
+            } catch (URISyntaxException e) {
+                Log.e(TAG, "Unable to add meta-favorite: " + uri, e);
+                return -1;
+            }
+
+            ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent,
+                    PackageManager.MATCH_DEFAULT_ONLY);
+            final List<ResolveInfo> appList = mPackageManager.queryIntentActivities(
+                    metaIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+            // Verify that the result is an app and not just the resolver dialog asking which
+            // app to use.
+            if (wouldLaunchResolverActivity(resolved, appList)) {
+                // If only one of the results is a system app then choose that as the default.
+                final ResolveInfo systemApp = getSingleSystemActivity(appList);
+                if (systemApp == null) {
+                    // There is no logical choice for this meta-favorite, so rather than making
+                    // a bad choice just add nothing.
+                    Log.w(TAG, "No preference or single system activity found for "
+                            + metaIntent.toString());
+                    return -1;
+                }
+                resolved = systemApp;
+            }
+            final ActivityInfo info = resolved.activityInfo;
+            final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName);
+            if (intent == null) {
+                return -1;
+            }
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+            return addShortcut(info.loadLabel(mPackageManager).toString(), intent,
+                    Favorites.ITEM_TYPE_APPLICATION);
+        }
+
+        private ResolveInfo getSingleSystemActivity(List<ResolveInfo> appList) {
+            ResolveInfo systemResolve = null;
+            final int N = appList.size();
+            for (int i = 0; i < N; ++i) {
+                try {
+                    ApplicationInfo info = mPackageManager.getApplicationInfo(
+                            appList.get(i).activityInfo.packageName, 0);
+                    if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        if (systemResolve != null) {
+                            return null;
+                        } else {
+                            systemResolve = appList.get(i);
+                        }
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Unable to get info about resolve results", e);
+                    return null;
+                }
+            }
+            return systemResolve;
+        }
+
+        private boolean wouldLaunchResolverActivity(ResolveInfo resolved,
+                List<ResolveInfo> appList) {
+            // If the list contains the above resolved activity, then it can't be
+            // ResolverActivity itself.
+            for (int i = 0; i < appList.size(); ++i) {
+                ResolveInfo tmp = appList.get(i);
+                if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
+                        && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+
+    /**
+     * Shortcut parser which allows any uri and not just web urls.
+     */
+    private class UriShortcutParser extends ShortcutParser {
+
+        public UriShortcutParser(Resources iconRes) {
+            super(iconRes);
+        }
+
+        @Override
+        protected Intent parseIntent(XmlResourceParser parser) {
+            String uri = null;
+            try {
+                uri = getAttributeValue(parser, ATTR_URI);
+                return Intent.parseUri(uri, 0);
+            } catch (URISyntaxException e) {
+                Log.w(TAG, "Shortcut has malformed uri: " + uri);
+                return null; // Oh well
+            }
+        }
+    }
+
+    /**
+     * Contains a list of <favorite> nodes, and accepts the first successfully parsed node.
+     */
+    private class ResolveParser implements TagParser {
+
+        private final AppShortcutWithUriParser mChildParser = new AppShortcutWithUriParser();
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+                IOException {
+            final int groupDepth = parser.getDepth();
+            int type;
+            long addedId = -1;
+            while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                    parser.getDepth() > groupDepth) {
+                if (type != XmlPullParser.START_TAG || addedId > -1) {
+                    continue;
+                }
+                final String fallback_item_name = parser.getName();
+                if (TAG_FAVORITE.equals(fallback_item_name)) {
+                    addedId = mChildParser.parseAndAdd(parser);
+                } else {
+                    Log.e(TAG, "Fallback groups can contain only favorites, found "
+                            + fallback_item_name);
+                }
+            }
+            return addedId;
+        }
+    }
+
+    /**
+     * A parser which adds a folder whose contents come from partner apk.
+     */
+    private class PartnerFolderParser implements TagParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+                IOException {
+            // Folder contents come from an external XML resource
+            final Partner partner = Partner.get(mPackageManager);
+            if (partner != null) {
+                final Resources partnerRes = partner.getResources();
+                final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
+                        "xml", partner.getPackageName());
+                if (resId != 0) {
+                    final XmlResourceParser partnerParser = partnerRes.getXml(resId);
+                    beginDocument(partnerParser, TAG_FOLDER);
+
+                    FolderParser folderParser = new FolderParser(getFolderElementsMap(partnerRes));
+                    return folderParser.parseAndAdd(partnerParser);
+                }
+            }
+            return -1;
+        }
+    }
+
+    /**
+     * An extension of FolderParser which allows adding items from a different xml.
+     */
+    private class MyFolderParser extends FolderParser {
+
+        @Override
+        public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+                IOException {
+            final int resId = getAttributeResourceValue(parser, ATTR_FOLDER_ITEMS, 0);
+            if (resId != 0) {
+                parser = mSourceRes.getXml(resId);
+                beginDocument(parser, TAG_FOLDER);
+            }
+            return super.parseAndAdd(parser);
+        }
+    }
+}
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/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index daf5556..b2366bb 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -75,7 +75,6 @@
     private float hotseatIconSize;
 
     int defaultLayoutId;
-    int defaultNoAllAppsLayoutId;
 
     boolean isLandscape;
     boolean isTablet;
@@ -136,7 +135,7 @@
     private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
 
     DeviceProfile(String n, float w, float h, float r, float c,
-                  float is, float its, float hs, float his, int dlId, int dnalId) {
+                  float is, float its, float hs, float his, int dlId) {
         // Ensure that we have an odd number of hotseat items (since we need to place all apps)
         if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
             throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
@@ -152,7 +151,6 @@
         numHotseatIcons = hs;
         hotseatIconSize = his;
         defaultLayoutId = dlId;
-        defaultNoAllAppsLayoutId = dnalId;
     }
 
     DeviceProfile() {
@@ -215,9 +213,6 @@
         // Snap to the closest default layout id
         defaultLayoutId = closestProfile.defaultLayoutId;
 
-        // Snap to the closest default no all-apps layout id
-        defaultNoAllAppsLayoutId = closestProfile.defaultNoAllAppsLayoutId;
-
         // Interpolate the icon size
         points.clear();
         for (DeviceProfile p : profiles) {
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 94a07d7..aa08148 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -60,41 +60,30 @@
         DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
         // Our phone profiles include the bar sizes in each orientation
         deviceProfiles.add(new DeviceProfile("Super Short Stubby",
-                255, 300,  2, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                255, 300,  2, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Shorter Stubby",
-                255, 400,  3, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                255, 400,  3, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Short Stubby",
-                275, 420,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                275, 420,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Stubby",
-                255, 450,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                255, 450,  3, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Nexus S",
-                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Nexus 4",
-                335, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                335, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Nexus 5",
-                359, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                359, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
         deviceProfiles.add(new DeviceProfile("Large Phone",
-                406, 694,  5, 5,  64, 14.4f,  5, 56, R.xml.default_workspace_5x5,
-                R.xml.default_workspace_5x5_no_all_apps));
+                406, 694,  5, 5,  64, 14.4f,  5, 56, R.xml.default_workspace_5x5));
         // The tablet profile is odd in that the landscape orientation
         // also includes the nav bar on the side
         deviceProfiles.add(new DeviceProfile("Nexus 7",
-                575, 904,  5, 6,  72, 14.4f,  7, 60, R.xml.default_workspace_5x6,
-                R.xml.default_workspace_5x6_no_all_apps));
+                575, 904,  5, 6,  72, 14.4f,  7, 60, R.xml.default_workspace_5x6));
         // Larger tablet profiles always have system bars on the top & bottom
         deviceProfiles.add(new DeviceProfile("Nexus 10",
-                727, 1207,  5, 6,  76, 14.4f,  7, 64, R.xml.default_workspace_5x6,
-                R.xml.default_workspace_5x6_no_all_apps));
+                727, 1207,  5, 6,  76, 14.4f,  7, 64, R.xml.default_workspace_5x6));
         deviceProfiles.add(new DeviceProfile("20-inch Tablet",
-                1527, 2527,  7, 7,  100, 20,  7, 72, R.xml.default_workspace_4x4,
-                R.xml.default_workspace_4x4_no_all_apps));
+                1527, 2527,  7, 7,  100, 20,  7, 72, R.xml.default_workspace_4x4));
         mMinWidth = dpiFromPx(minWidthPx, dm);
         mMinHeight = dpiFromPx(minHeightPx, dm);
         mProfile = new DeviceProfile(context, deviceProfiles,
diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java
index 12b7a40..7d4664a 100644
--- a/src/com/android/launcher3/FocusIndicatorView.java
+++ b/src/com/android/launcher3/FocusIndicatorView.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3;
 
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.util.AttributeSet;
@@ -28,6 +30,7 @@
     // It can be any number >0. The view is resized using scaleX and scaleY.
     static final int DEFAULT_LAYOUT_SIZE = 100;
     private static final float MIN_VISIBLE_ALPHA = 0.2f;
+    private static final long ANIM_DURATION = 150;
 
     private static final int[] sTempPos = new int[2];
     private static final int[] sTempShift = new int[2];
@@ -35,6 +38,9 @@
     private final int[] mIndicatorPos = new int[2];
     private final int[] mTargetViewPos = new int[2];
 
+    private ObjectAnimator mCurrentAnimation;
+    private ViewAnimState mTargetState;
+
     private View mLastFocusedView;
     private boolean mInitiated;
 
@@ -82,34 +88,58 @@
             int indicatorWidth = getWidth();
             int indicatorHeight = getHeight();
 
-            float scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
-            float scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
+            endCurrentAnimation();
+            ViewAnimState nextState = new ViewAnimState();
+            nextState.scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
+            nextState.scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
 
             getLocationRelativeToParentPagedView(v, mTargetViewPos);
-            float x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - scaleX) * indicatorWidth / 2;
-            float y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - scaleY) * indicatorHeight / 2;
+            nextState.x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - nextState.scaleX) * indicatorWidth / 2;
+            nextState.y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - nextState.scaleY) * indicatorHeight / 2;
 
             if (getAlpha() > MIN_VISIBLE_ALPHA) {
-                animate()
-                .translationX(x)
-                .translationY(y)
-                .scaleX(scaleX)
-                .scaleY(scaleY)
-                .alpha(1);
+                mTargetState = nextState;
+                mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+                        PropertyValuesHolder.ofFloat(View.ALPHA, 1),
+                        PropertyValuesHolder.ofFloat(View.TRANSLATION_X, mTargetState.x),
+                        PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, mTargetState.y),
+                        PropertyValuesHolder.ofFloat(View.SCALE_X, mTargetState.scaleX),
+                        PropertyValuesHolder.ofFloat(View.SCALE_Y, mTargetState.scaleY));
             } else {
-                setTranslationX(x);
-                setTranslationY(y);
-                setScaleX(scaleX);
-                setScaleY(scaleY);
-                animate().alpha(1);
+                applyState(nextState);
+                mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+                        PropertyValuesHolder.ofFloat(View.ALPHA, 1));
             }
             mLastFocusedView = v;
         } else {
             if (mLastFocusedView == v) {
                 mLastFocusedView = null;
-                animate().alpha(0);
+                endCurrentAnimation();
+                mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+                        PropertyValuesHolder.ofFloat(View.ALPHA, 0));
             }
         }
+        if (mCurrentAnimation != null) {
+            mCurrentAnimation.setDuration(ANIM_DURATION).start();
+        }
+    }
+
+    private void endCurrentAnimation() {
+        if (mCurrentAnimation != null) {
+            mCurrentAnimation.cancel();
+            mCurrentAnimation = null;
+        }
+        if (mTargetState != null) {
+            applyState(mTargetState);
+            mTargetState = null;
+        }
+    }
+
+    private void applyState(ViewAnimState state) {
+        setTranslationX(state.x);
+        setTranslationY(state.y);
+        setScaleX(state.scaleX);
+        setScaleY(state.scaleY);
     }
 
     @Override
@@ -143,4 +173,8 @@
             shift[0] = shift[1] = 0;
         }
     }
+
+    private static final class ViewAnimState {
+        float x, y, scaleX, scaleY;
+    }
 }
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 06f9f29..5a0875b 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -24,7 +24,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -117,8 +116,7 @@
     }
 
     public Drawable getFullResDefaultActivityIcon() {
-        return getFullResIcon(Resources.getSystem(),
-                android.R.mipmap.sym_def_app_icon);
+        return getFullResIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
     }
 
     private Drawable getFullResIcon(Resources resources, int iconId) {
@@ -151,12 +149,7 @@
         return mIconDpi;
     }
 
-    public Drawable getFullResIcon(ResolveInfo info) {
-        return getFullResIcon(info.activityInfo);
-    }
-
     public Drawable getFullResIcon(ActivityInfo info) {
-
         Resources resources;
         try {
             resources = mPackageManager.getResourcesForApplication(
@@ -190,16 +183,14 @@
     /**
      * Remove any records for the supplied ComponentName.
      */
-    public void remove(ComponentName componentName, UserHandleCompat user) {
-        synchronized (mCache) {
-            mCache.remove(new CacheKey(componentName, user));
-        }
+    public synchronized void remove(ComponentName componentName, UserHandleCompat user) {
+        mCache.remove(new CacheKey(componentName, user));
     }
 
     /**
      * Remove any records for the supplied package name.
      */
-    public void remove(String packageName, UserHandleCompat user) {
+    public synchronized void remove(String packageName, UserHandleCompat user) {
         HashSet<CacheKey> forDeletion = new HashSet<CacheKey>();
         for (CacheKey key: mCache.keySet()) {
             if (key.componentName.getPackageName().equals(packageName)
@@ -215,24 +206,20 @@
     /**
      * Empty out the cache.
      */
-    public void flush() {
-        synchronized (mCache) {
-            mCache.clear();
-        }
+    public synchronized void flush() {
+        mCache.clear();
     }
 
     /**
      * Empty out the cache that aren't of the correct grid size
      */
-    public void flushInvalidIcons(DeviceProfile grid) {
-        synchronized (mCache) {
-            Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
-            while (it.hasNext()) {
-                final CacheEntry e = it.next().getValue();
-                if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
-                        || e.icon.getHeight() < grid.iconSizePx)) {
-                    it.remove();
-                }
+    public synchronized void flushInvalidIcons(DeviceProfile grid) {
+        Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
+        while (it.hasNext()) {
+            final CacheEntry e = it.next().getValue();
+            if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
+                    || e.icon.getHeight() < grid.iconSizePx)) {
+                it.remove();
             }
         }
     }
@@ -240,90 +227,78 @@
     /**
      * Fill in "application" with the icon and label for "info."
      */
-    public void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
+    public synchronized void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
             HashMap<Object, CharSequence> labelCache) {
-        synchronized (mCache) {
-            CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
-                    info.getUser(), false);
+        CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
+                info.getUser(), false);
 
-            application.title = entry.title;
-            application.iconBitmap = entry.icon;
-            application.contentDescription = entry.contentDescription;
-        }
+        application.title = entry.title;
+        application.iconBitmap = entry.icon;
+        application.contentDescription = entry.contentDescription;
     }
 
-    public Bitmap getIcon(Intent intent, UserHandleCompat user) {
-        return getIcon(intent, null, user, true);
-    }
-
-    private Bitmap getIcon(Intent intent, String title, UserHandleCompat user, boolean usePkgIcon) {
-        synchronized (mCache) {
-            ComponentName component = intent.getComponent();
-            // null info means not installed, but if we have a component from the intent then
-            // we should still look in the cache for restored app icons.
-            if (component == null) {
-                return getDefaultIcon(user);
-            }
-
-            LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
-            CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
-            if (title != null) {
-                entry.title = title;
-                entry.contentDescription = mUserManager.getBadgedLabelForUser(title, user);
-            }
-            return entry.icon;
+    public synchronized Bitmap getIcon(Intent intent, UserHandleCompat user) {
+        ComponentName component = intent.getComponent();
+        // null info means not installed, but if we have a component from the intent then
+        // we should still look in the cache for restored app icons.
+        if (component == null) {
+            return getDefaultIcon(user);
         }
+
+        LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
+        CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, true);
+        return entry.icon;
     }
 
     /**
      * Fill in "shortcutInfo" with the icon and label for "info."
      */
-    public void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent, UserHandleCompat user,
-            boolean usePkgIcon) {
-        synchronized (mCache) {
-            ComponentName component = intent.getComponent();
-            // null info means not installed, but if we have a component from the intent then
-            // we should still look in the cache for restored app icons.
-            if (component == null) {
-                shortcutInfo.setIcon(getDefaultIcon(user));
-                shortcutInfo.title = "";
-                shortcutInfo.usingFallbackIcon = true;
-            } else {
-                LauncherActivityInfoCompat launcherActInfo =
-                        mLauncherApps.resolveActivity(intent, user);
-                CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
+    public synchronized void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent,
+            UserHandleCompat user, boolean usePkgIcon) {
+        ComponentName component = intent.getComponent();
+        // null info means not installed, but if we have a component from the intent then
+        // we should still look in the cache for restored app icons.
+        if (component == null) {
+            shortcutInfo.setIcon(getDefaultIcon(user));
+            shortcutInfo.title = "";
+            shortcutInfo.usingFallbackIcon = true;
+        } else {
+            LauncherActivityInfoCompat launcherActInfo =
+                    mLauncherApps.resolveActivity(intent, user);
+            CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
 
-                shortcutInfo.setIcon(entry.icon);
-                shortcutInfo.title = entry.title;
-                shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
-            }
+            shortcutInfo.setIcon(entry.icon);
+            shortcutInfo.title = entry.title;
+            shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
         }
     }
 
 
-    public Bitmap getDefaultIcon(UserHandleCompat user) {
+    public synchronized Bitmap getDefaultIcon(UserHandleCompat user) {
         if (!mDefaultIcons.containsKey(user)) {
             mDefaultIcons.put(user, makeDefaultIcon(user));
         }
         return mDefaultIcons.get(user);
     }
 
-    public Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
+    public synchronized Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
             HashMap<Object, CharSequence> labelCache) {
-        synchronized (mCache) {
-            if (info == null || component == null) {
-                return null;
-            }
-
-            CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
-            return entry.icon;
+        if (info == null || component == null) {
+            return null;
         }
+
+        CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
+        return entry.icon;
     }
 
     public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
         return mDefaultIcons.get(user) == icon;
     }
 
+    /**
+     * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
+     * This method is not thread safe, it must be called from a synchronized method.
+     */
     private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
             HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
         CacheKey cacheKey = new CacheKey(componentName, user);
@@ -380,7 +355,7 @@
      * Adds a default package entry in the cache. This entry is not persisted and will be removed
      * when the cache is flushed.
      */
-    public void cachePackageInstallInfo(String packageName, UserHandleCompat user,
+    public synchronized void cachePackageInstallInfo(String packageName, UserHandleCompat user,
             Bitmap icon, CharSequence title) {
         remove(packageName, user);
 
@@ -395,9 +370,10 @@
 
     /**
      * Gets an entry for the package, which can be used as a fallback entry for various components.
+     * This method is not thread safe, it must be called from a synchronized method.
      */
     private CacheEntry getEntryForPackage(String packageName, UserHandleCompat user) {
-        ComponentName cn = getPackageComponent(packageName);
+        ComponentName cn = new ComponentName(packageName, EMPTY_CLASS_NAME);;
         CacheKey cacheKey = new CacheKey(cn, user);
         CacheEntry entry = mCache.get(cacheKey);
         if (entry == null) {
@@ -420,15 +396,13 @@
         return entry;
     }
 
-    public HashMap<ComponentName,Bitmap> getAllIcons() {
-        synchronized (mCache) {
-            HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
-            for (CacheKey ck : mCache.keySet()) {
-                final CacheEntry e = mCache.get(ck);
-                set.put(ck.componentName, e.icon);
-            }
-            return set;
+    public synchronized HashMap<ComponentName,Bitmap> getAllIcons() {
+        HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
+        for (CacheKey ck : mCache.keySet()) {
+            final CacheEntry e = mCache.get(ck);
+            set.put(ck.componentName, e.icon);
         }
+        return set;
     }
 
     /**
@@ -534,23 +508,15 @@
      * Remove a pre-loaded icon from the persistent icon cache.
      *
      * @param componentName the component that should own the icon
-     * @returns true on success
      */
-    public boolean deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
+    public void deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
         // We don't keep icons for other profiles in persistent cache.
-        if (!user.equals(UserHandleCompat.myUserHandle())) {
-            return false;
+        if (!user.equals(UserHandleCompat.myUserHandle()) || componentName == null) {
+            return;
         }
-        if (componentName == null) {
-            return false;
-        }
-        if (mCache.remove(componentName) != null) {
-            if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
-        }
+        remove(componentName, user);
         boolean success = mContext.deleteFile(getResourceFilename(componentName));
         if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
-
-        return success;
     }
 
     private static String getResourceFilename(ComponentName component) {
@@ -558,8 +524,4 @@
         String filename = resourceName.replace(File.separatorChar, '_');
         return RESOURCE_FILE_PREFIX + filename;
     }
-
-    static ComponentName getPackageComponent(String packageName) {
-        return new ComponentName(packageName, EMPTY_CLASS_NAME);
-    }
 }
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 2edde4f..e9fb499 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -17,7 +17,6 @@
 package com.android.launcher3;
 
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -45,17 +44,17 @@
     private static final String TAG = "InstallShortcutReceiver";
     private static final boolean DBG = false;
 
-    public static final String ACTION_INSTALL_SHORTCUT =
+    private static final String ACTION_INSTALL_SHORTCUT =
             "com.android.launcher.action.INSTALL_SHORTCUT";
 
-    public static final String DATA_INTENT_KEY = "intent.data";
-    public static final String LAUNCH_INTENT_KEY = "intent.launch";
-    public static final String NAME_KEY = "name";
-    public static final String ICON_KEY = "icon";
-    public static final String ICON_RESOURCE_NAME_KEY = "iconResource";
-    public static final String ICON_RESOURCE_PACKAGE_NAME_KEY = "iconResourcePackage";
+    private static final String DATA_INTENT_KEY = "intent.data";
+    private static final String LAUNCH_INTENT_KEY = "intent.launch";
+    private static final String NAME_KEY = "name";
+    private static final String ICON_KEY = "icon";
+    private static final String ICON_RESOURCE_NAME_KEY = "iconResource";
+    private static final String ICON_RESOURCE_PACKAGE_NAME_KEY = "iconResourcePackage";
     // The set of shortcuts that are pending install
-    public static final String APPS_PENDING_INSTALL = "apps_to_install";
+    private static final String APPS_PENDING_INSTALL = "apps_to_install";
 
     public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
     public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
@@ -63,17 +62,13 @@
     private static final int INSTALL_SHORTCUT_SUCCESSFUL = 0;
     private static final int INSTALL_SHORTCUT_IS_DUPLICATE = -1;
 
-    // A mime-type representing shortcut data
-    public static final String SHORTCUT_MIMETYPE =
-            "com.android.launcher3/shortcut";
-
     private static Object sLock = new Object();
 
     private static void addToStringSet(SharedPreferences sharedPrefs,
             SharedPreferences.Editor editor, String key, String value) {
         Set<String> strings = sharedPrefs.getStringSet(key, null);
         if (strings == null) {
-            strings = new HashSet<String>(0);
+            strings = new HashSet<String>(1);
         } else {
             strings = new HashSet<String>(strings);
         }
@@ -133,6 +128,9 @@
                         Intent launchIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0);
                         String pn = launchIntent.getPackage();
                         if (pn == null) {
+                            if (launchIntent.getComponent() == null) {
+                                continue;
+                            }
                             pn = launchIntent.getComponent().getPackageName();
                         }
                         if (packageNames.contains(pn)) {
@@ -355,7 +353,7 @@
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         }
         LauncherAppState app = LauncherAppState.getInstance();
-        ShortcutInfo info = app.getModel().infoFromShortcutIntent(context, data, null);
+        ShortcutInfo info = app.getModel().infoFromShortcutIntent(context, data);
         info.title = ensureValidName(context, launchIntent, info.title);
         return info;
     }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3762c2f..178f6cb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -404,6 +404,10 @@
                     .build());
         }
 
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.preOnCreate();
+        }
+
         super.onCreate(savedInstanceState);
 
         LauncherAppState.setApplicationContext(getApplicationContext());
@@ -500,13 +504,38 @@
             showFirstRunActivity();
             showFirstRunClings();
         }
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onCreate(savedInstanceState);
+        }
+    }
+
+    private LauncherCallbacks mLauncherCallbacks;
+
+    public void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onPostCreate(savedInstanceState);
+        }
+    }
+
+    public boolean setLauncherCallbacks(LauncherCallbacks callbacks) {
+        mLauncherCallbacks = callbacks;
+        return true;
     }
 
     @Override
-    public void onLauncherProviderChange() { }
+    public void onLauncherProviderChange() {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onLauncherProviderChange();
+        }
+    }
 
-    /** To be overriden by subclasses to hint to Launcher that we have custom content */
+    /** To be overridden by subclasses to hint to Launcher that we have custom content */
     protected boolean hasCustomContentToLeft() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.hasCustomContentToLeft();
+        }
         return false;
     }
 
@@ -516,6 +545,9 @@
      * {@link #hasCustomContentToLeft()} is {@code true}.
      */
     protected void populateCustomContentContainer() {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.populateCustomContentContainer();
+        }
     }
 
     /**
@@ -617,7 +649,7 @@
     private static void readConfiguration(Context context, LocaleConfiguration configuration) {
         DataInputStream in = null;
         try {
-            in = new DataInputStream(context.openFileInput(LauncherFiles.LAUNCHER_PREFS));
+            in = new DataInputStream(context.openFileInput(LauncherFiles.LAUNCHER_PREFERENCES));
             configuration.locale = in.readUTF();
             configuration.mcc = in.readInt();
             configuration.mnc = in.readInt();
@@ -640,7 +672,7 @@
         DataOutputStream out = null;
         try {
             out = new DataOutputStream(context.openFileOutput(
-                    LauncherFiles.LAUNCHER_PREFS, MODE_PRIVATE));
+                    LauncherFiles.LAUNCHER_PREFERENCES, MODE_PRIVATE));
             out.writeUTF(configuration.locale);
             out.writeInt(configuration.mcc);
             out.writeInt(configuration.mnc);
@@ -649,7 +681,7 @@
             // Ignore
         } catch (IOException e) {
             //noinspection ResultOfMethodCallIgnored
-            context.getFileStreamPath(LauncherFiles.LAUNCHER_PREFS).delete();
+            context.getFileStreamPath(LauncherFiles.LAUNCHER_PREFERENCES).delete();
         } finally {
             if (out != null) {
                 try {
@@ -954,12 +986,20 @@
     protected void onStop() {
         super.onStop();
         FirstFrameAnimatorHelper.setIsVisible(false);
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onStop();
+        }
     }
 
     @Override
     protected void onStart() {
         super.onStart();
         FirstFrameAnimatorHelper.setIsVisible(true);
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onStart();
+        }
     }
 
     @Override
@@ -969,6 +1009,11 @@
             startTime = System.currentTimeMillis();
             Log.v(TAG, "Launcher.onResume()");
         }
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.preOnResume();
+        }
+
         super.onResume();
 
         // Restore the previous launcher state
@@ -1057,6 +1102,10 @@
         mWorkspace.onResume();
 
         PackageInstallerCompat.getInstance(this).onResume();
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onResume();
+        }
     }
 
     @Override
@@ -1075,25 +1124,10 @@
         if (mWorkspace.getCustomContentCallbacks() != null) {
             mWorkspace.getCustomContentCallbacks().onHide();
         }
-    }
 
-    QSBScroller mQsbScroller = new QSBScroller() {
-        int scrollY = 0;
-
-        @Override
-        public void setScrollY(int scroll) {
-            scrollY = scroll;
-
-            if (mWorkspace.isOnOrMovingToCustomContent()) {
-                mSearchDropTargetBar.setTranslationY(- scrollY);
-                getQsbBar().setTranslationY(-scrollY);
-            }
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onPause();
         }
-    };
-
-    public void resetQSBScroll() {
-        mSearchDropTargetBar.animate().translationY(0).start();
-        getQsbBar().animate().translationY(0).start();
     }
 
     public interface CustomContentCallbacks {
@@ -1112,17 +1146,16 @@
     }
 
     protected boolean hasSettings() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.hasSettings();
+        }
         return false;
     }
 
-    public interface QSBScroller {
-        public void setScrollY(int scrollY);
-    }
 
-    public QSBScroller addToCustomContentPage(View customContent,
+    public void addToCustomContentPage(View customContent,
             CustomContentCallbacks callbacks, String description) {
         mWorkspace.addToCustomContentPage(customContent, callbacks, description);
-        return mQsbScroller;
     }
 
     // The custom content needs to offset its content to account for the QSB
@@ -1147,6 +1180,10 @@
     public void onWindowFocusChanged(boolean hasFocus) {
         super.onWindowFocusChanged(hasFocus);
         mHasFocus = hasFocus;
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onWindowFocusChanged(hasFocus);
+        }
     }
 
     private boolean acceptFilter() {
@@ -1333,9 +1370,6 @@
             settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
         } else {
             settingsButton.setVisibility(View.GONE);
-            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) widgetButton.getLayoutParams();
-            lp.gravity = Gravity.END | Gravity.TOP;
-            widgetButton.requestLayout();
         }
 
         mOverviewPanel.setAlpha(0f);
@@ -1435,7 +1469,7 @@
 
         boolean foundCellSpan = false;
 
-        ShortcutInfo info = mModel.infoFromShortcutIntent(this, data, null);
+        ShortcutInfo info = mModel.infoFromShortcutIntent(this, data);
         if (info == null) {
             return;
         }
@@ -1885,8 +1919,11 @@
             Folder openFolder = mWorkspace.getOpenFolder();
             // In all these cases, only animate if we're already on home
             mWorkspace.exitWidgetResizeMode();
+
+            boolean moveToDefaultScreen = mLauncherCallbacks != null ?
+                    mLauncherCallbacks.shouldMoveToDefaultScreenOnHomeIntent() : true;
             if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() &&
-                    openFolder == null && shouldMoveToDefaultScreenOnHomeIntent()) {
+                    openFolder == null && moveToDefaultScreen) {
                 mWorkspace.moveToDefaultScreen(true);
             }
 
@@ -1913,27 +1950,18 @@
                 mAppsCustomizeTabHost.reset();
             }
 
-            onHomeIntent();
+            if (mLauncherCallbacks != null) {
+                mLauncherCallbacks.onHomeIntent();
+            }
         }
 
         if (DEBUG_RESUME_TIME) {
             Log.d(TAG, "Time spent in onNewIntent: " + (System.currentTimeMillis() - startTime));
         }
-    }
 
-    /**
-     * Override point for subclasses to prevent movement to the default screen when the home
-     * button is pressed. Used (for example) in GEL, to prevent movement during a search.
-     */
-    protected boolean shouldMoveToDefaultScreenOnHomeIntent() {
-        return true;
-    }
-
-    /**
-     * Override point for subclasses to provide custom behaviour for when a home intent is fired.
-     */
-    protected void onHomeIntent() {
-        // Do nothing
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onNewIntent(intent);
+        }
     }
 
     @Override
@@ -1985,6 +2013,10 @@
             outState.putInt("apps_customize_currentIndex", currentIndex);
         }
         outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId);
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onSaveInstanceState(outState);
+        }
     }
 
     @Override
@@ -2033,6 +2065,10 @@
         mDragController = null;
 
         LauncherAnimUtils.onDestroyActivity();
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onDestroy();
+        }
     }
 
     public DragController getDragController() {
@@ -2086,6 +2122,11 @@
      */
     public boolean startSearch(String initialQuery,
             boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            return mLauncherCallbacks.startSearch(initialQuery, selectInitialQuery, appSearchData,
+                    sourceBounds);
+        }
+
         startGlobalSearch(initialQuery, selectInitialQuery,
                 appSearchData, sourceBounds);
         return false;
@@ -2112,7 +2153,7 @@
         } else {
             appSearchData = new Bundle(appSearchData);
         }
-        // Set source to package name of app that starts global search, if not set already.
+        // Set source to package name of app that starts global search if not set already.
         if (!appSearchData.containsKey("source")) {
             appSearchData.putString("source", getPackageName());
         }
@@ -2150,6 +2191,10 @@
                 showWorkspace(true);
             }
         }
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.onPrepareOptionsMenu(menu);
+        }
+
         return false;
     }
 
@@ -2184,7 +2229,11 @@
         }
     }
 
-    protected void onWorkspaceLockedChanged() { }
+    protected void onWorkspaceLockedChanged() {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onWorkspaceLockedChanged();
+        }
+    }
 
     private void resetAddInfo() {
         mPendingAddInfo.container = ItemInfo.NO_ID;
@@ -2346,6 +2395,9 @@
     }
 
     protected ComponentName getWallpaperPickerComponent() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.getWallpaperPickerComponent();
+        }
         return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
     }
 
@@ -2384,6 +2436,10 @@
 
     @Override
     public void onBackPressed() {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.handleBackPressed()) {
+            return;
+        }
+
         if (isAllAppsVisible()) {
             if (mAppsCustomizeContent.getContentType() ==
                     AppsCustomizePagedView.ContentType.Applications) {
@@ -2466,6 +2522,9 @@
 
     public void onClickPagedViewIcon(View v) {
         startAppShortcutOrInfoActivity(v);
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickPagedViewIcon(v);
+        }
     }
 
     public boolean onTouch(View v, MotionEvent event) {
@@ -2476,6 +2535,11 @@
      * Event handler for the app widget view which has not fully restored.
      */
     public void onClickPendingWidget(final PendingAppWidgetHostView v) {
+        if (mIsSafeModeEnabled) {
+            Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+            return;
+        }
+
         final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
         if (v.isReadyForClickSetup()) {
             int widgetId = info.appWidgetId;
@@ -2527,6 +2591,11 @@
     }
 
     public void startVoice() {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            mLauncherCallbacks.startVoice();
+            return;
+        }
+
         try {
             final SearchManager searchManager =
                     (SearchManager) getSystemService(Context.SEARCH_SERVICE);
@@ -2557,6 +2626,9 @@
         } else {
             showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
         }
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickAllAppsButton(v);
+        }
     }
 
     private void showBrokenAppInstallDialog(final String packageName,
@@ -2631,6 +2703,10 @@
 
         // Start activities
         startAppShortcutOrInfoActivity(v);
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickAppShortcut(v);
+        }
     }
 
     private void startAppShortcutOrInfoActivity(View v) {
@@ -2704,6 +2780,10 @@
                 }
             }
         }
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickFolderIcon(v);
+        }
     }
 
     /**
@@ -2712,7 +2792,14 @@
      */
     protected void onClickAddWidgetButton(View view) {
         if (LOGD) Log.d(TAG, "onClickAddWidgetButton");
-        showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+        if (mIsSafeModeEnabled) {
+            Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+        } else {
+            showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+            if (mLauncherCallbacks != null) {
+                mLauncherCallbacks.onClickAddWidgetButton(view);
+            }
+        }
     }
 
     /**
@@ -2724,6 +2811,10 @@
         final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
         pickWallpaper.setComponent(getWallpaperPickerComponent());
         startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickWallpaperPicker(v);
+        }
     }
 
     /**
@@ -2732,6 +2823,9 @@
      */
     protected void onClickSettingsButton(View v) {
         if (LOGD) Log.d(TAG, "onClickSettingsButton");
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onClickSettingsButton(v);
+        }
     }
 
     public void onTouchDownAllAppsButton(View v) {
@@ -2759,13 +2853,27 @@
         return mHapticFeedbackTouchListener;
     }
 
-    public void onDragStarted(View view) {}
+    public void onDragStarted(View view) {
+        if (isOnCustomContent()) {
+            // Custom content screen doesn't participate in drag and drop. If on custom
+            // content screen, move to default.
+            moveWorkspaceToDefaultScreen();
+        }
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onDragStarted(view);
+        }
+    }
 
     /**
      * Called when the user stops interacting with the launcher.
      * This implies that the user is now on the homescreen and is not doing housekeeping.
      */
-    protected void onInteractionEnd() {}
+    protected void onInteractionEnd() {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onInteractionEnd();
+        }
+    }
 
     /**
      * Called when the user starts interacting with the launcher.
@@ -2776,7 +2884,11 @@
      * This is a good time to stop doing things that only make sense
      * when the user is on the homescreen and not doing housekeeping.
      */
-    protected void onInteractionBegin() {}
+    protected void onInteractionBegin() {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onInteractionBegin();
+        }
+    }
 
     void startApplicationDetailsActivity(ComponentName componentName, UserHandleCompat user) {
         String packageName = componentName.getPackageName();
@@ -3972,6 +4084,13 @@
     }
 
     public View getQsbBar() {
+        if (mLauncherCallbacks != null) {
+            View qsb = mLauncherCallbacks.getQsbBar();
+            if (qsb != null) {
+                return qsb;
+            }
+        }
+
         if (mQsb == null) {
             mQsb = mInflater.inflate(R.layout.qsb, mSearchDropTargetBar, false);
             mSearchDropTargetBar.addView(mQsb);
@@ -3980,6 +4099,10 @@
     }
 
     protected boolean updateGlobalSearchIcon() {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            return true;
+        }
+
         final View searchButtonContainer = findViewById(R.id.search_button_container);
         final ImageView searchButton = (ImageView) findViewById(R.id.search_button);
         final View voiceButtonContainer = findViewById(R.id.voice_button_container);
@@ -4015,6 +4138,7 @@
     }
 
     protected void updateGlobalSearchIcon(Drawable.ConstantState d) {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) return;
         final View searchButtonContainer = findViewById(R.id.search_button_container);
         final View searchButton = (ImageView) findViewById(R.id.search_button);
         updateButtonWithDrawable(R.id.search_button, d);
@@ -4022,6 +4146,9 @@
     }
 
     protected boolean updateVoiceSearchIcon(boolean searchVisible) {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            return true;
+        }
         final View voiceButtonContainer = findViewById(R.id.voice_button_container);
         final View voiceButton = findViewById(R.id.voice_button);
 
@@ -4068,6 +4195,10 @@
     }
 
     protected void updateVoiceSearchIcon(Drawable.ConstantState d) {
+        if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+            return;
+        }
+
         final View voiceButtonContainer = findViewById(R.id.voice_button_container);
         final View voiceButton = findViewById(R.id.voice_button);
         updateButtonWithDrawable(R.id.voice_button, d);
@@ -4075,6 +4206,9 @@
     }
 
     public void updateVoiceButtonProxyVisible(boolean forceDisableVoiceButtonProxy) {
+        if (mLauncherCallbacks != null) {
+            forceDisableVoiceButtonProxy |= mLauncherCallbacks.forceDisableVoiceButtonProxy();
+        }
         final View voiceButtonProxy = findViewById(R.id.voice_button_proxy);
         if (voiceButtonProxy != null) {
             boolean visible = !forceDisableVoiceButtonProxy &&
@@ -4462,8 +4596,9 @@
         final Workspace workspace = mWorkspace;
 
         AppWidgetProviderInfo appWidgetInfo;
-        if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) &&
-                ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
+        if (!mIsSafeModeEnabled
+                && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0)
+                && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
 
             appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName);
             if (appWidgetInfo == null) {
@@ -4513,7 +4648,7 @@
             LauncherModel.updateItemInDatabase(this, item);
         }
 
-        if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
+        if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
             final int appWidgetId = item.appWidgetId;
             appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
             if (DEBUG_WIDGETS) {
@@ -4523,7 +4658,8 @@
             item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
         } else {
             appWidgetInfo = null;
-            PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item);
+            PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item,
+                    mIsSafeModeEnabled);
             view.updateIcon(mIconCache);
             item.hostView = view;
             item.hostView.updateAppWidget(null);
@@ -4617,6 +4753,10 @@
             mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
         }
         PackageInstallerCompat.getInstance(this).onFinishBind();
+
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.finishBindingItems(upgradePath);
+        }
     }
 
     private void sendLoadingCompleteBroadcastIfNecessary() {
@@ -4698,6 +4838,9 @@
                         LauncherModel.getSortedWidgetsAndShortcuts(this));
             }
         }
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.bindAllApplications(apps);
+        }
     }
 
     /**
@@ -4916,16 +5059,10 @@
         }
     }
 
-    /**
-     * Called when the SearchBar hint should be changed.
-     *
-     * @param hint the hint to be displayed in the search bar.
-     */
-    protected void onSearchBarHintChanged(String hint) {
-
-    }
-
     protected boolean isLauncherPreinstalled() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.isLauncherPreinstalled();
+        }
         PackageManager pm = getPackageManager();
         try {
             ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0);
@@ -4945,6 +5082,9 @@
      * when our wallpaper cropper was not yet used to set a wallpaper.
      */
     protected boolean overrideWallpaperDimensions() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.overrideWallpaperDimensions();
+        }
         return true;
     }
 
@@ -4953,6 +5093,9 @@
      * before showing the standard launcher experience.
      */
     protected boolean hasFirstRunActivity() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.hasFirstRunActivity();
+        }
         return false;
     }
 
@@ -4960,6 +5103,9 @@
      * To be overridden by subclasses to launch any first run activity
      */
     protected Intent getFirstRunActivity() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.getFirstRunActivity();
+        }
         return null;
     }
 
@@ -4996,6 +5142,9 @@
      * screen that must be displayed and dismissed.
      */
     protected boolean hasDismissableIntroScreen() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.hasDismissableIntroScreen();
+        }
         return false;
     }
 
@@ -5003,6 +5152,9 @@
      * Full screen intro screen to be shown and dismissed before the launcher can be used.
      */
     protected View getIntroScreen() {
+        if (mLauncherCallbacks != null) {
+            return mLauncherCallbacks.getIntroScreen();
+        }
         return null;
     }
 
@@ -5114,6 +5266,9 @@
 
     @Override
     public void onPageSwitch(View newPage, int newPageIndex) {
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.onPageSwitch(newPage, newPageIndex);
+        }
     }
 
     /**
@@ -5145,6 +5300,9 @@
                 writer.println("  " + sDumpLogs.get(i));
             }
         }
+        if (mLauncherCallbacks != null) {
+            mLauncherCallbacks.dump(prefix, fd, writer, args);
+        }
     }
 
     public static void dumpDebugLogsToConsole() {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index ab0b135..03ab94b 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -37,7 +37,6 @@
 
 public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
     private static final String TAG = "LauncherAppState";
-    private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
 
     private static final boolean DEBUG = false;
 
@@ -188,7 +187,7 @@
     }
 
     public static String getSharedPreferencesKey() {
-        return SHARED_PREFERENCES_KEY;
+        return LauncherFiles.SHARED_PREFERENCES_KEY;
     }
 
     DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight,
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
new file mode 100644
index 0000000..aef2adc
--- /dev/null
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -0,0 +1,89 @@
+package com.android.launcher3;
+
+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 java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * LauncherCallbacks is an interface used to extend the Launcher activity. It includes many hooks
+ * in order to add additional functionality. Some of these are very general, and give extending
+ * classes the ability to react to Activity life-cycle or specific user interactions. Others
+ * are more specific and relate to replacing parts of the application, for example, the search
+ * interface or the wallpaper picker.
+ */
+public interface LauncherCallbacks {
+
+    /*
+     * Activity life-cycle methods. These methods are triggered after
+     * the code in the corresponding Launcher method is executed.
+     */
+    public void preOnCreate();
+    public void onCreate(Bundle savedInstanceState);
+    public void preOnResume();
+    public void onResume();
+    public void onStart();
+    public void onStop();
+    public void onPause();
+    public void onDestroy();
+    public void onSaveInstanceState(Bundle outState);
+    public void onPostCreate(Bundle savedInstanceState);
+    public void onNewIntent(Intent intent);
+    public void onActivityResult(int requestCode, int resultCode, Intent data);
+    public void onWindowFocusChanged(boolean hasFocus);
+    public boolean onPrepareOptionsMenu(Menu menu);
+    public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args);
+    public void onHomeIntent();
+    public boolean handleBackPressed();
+
+    /*
+     * Extension points for providing custom behavior on certain user interactions.
+     */
+    public void onLauncherProviderChange();
+    public void finishBindingItems(final boolean upgradePath);
+    public void onClickAllAppsButton(View v);
+    public void bindAllApplications(ArrayList<AppInfo> apps);
+    public void onClickFolderIcon(View v);
+    public void onClickAppShortcut(View v);
+    public void onClickPagedViewIcon(View v);
+    public void onClickWallpaperPicker(View v);
+    public void onClickSettingsButton(View v);
+    public void onClickAddWidgetButton(View v);
+    public void onPageSwitch(View newPage, int newPageIndex);
+    public void onWorkspaceLockedChanged();
+    public void onDragStarted(View view);
+    public void onInteractionBegin();
+    public void onInteractionEnd();
+
+    /*
+     * Extension points for replacing the search experience
+     */
+    public boolean forceDisableVoiceButtonProxy();
+    public boolean providesSearch();
+    public boolean startSearch(String initialQuery, boolean selectInitialQuery,
+            Bundle appSearchData, Rect sourceBounds);
+    public void startVoice();
+    public boolean hasCustomContentToLeft();
+    public void populateCustomContentContainer();
+    public View getQsbBar();
+
+    /*
+     * Extensions points for adding / replacing some other aspects of the Launcher experience.
+     */
+    public Intent getFirstRunActivity();
+    public boolean hasFirstRunActivity();
+    public boolean hasDismissableIntroScreen();
+    public View getIntroScreen();
+    public boolean shouldMoveToDefaultScreenOnHomeIntent();
+    public boolean hasSettings();
+    public ComponentName getWallpaperPickerComponent();
+    public boolean overrideWallpaperDimensions();
+    public boolean isLauncherPreinstalled();
+
+}
diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java
index 89600c2..fa05365 100644
--- a/src/com/android/launcher3/LauncherFiles.java
+++ b/src/com/android/launcher3/LauncherFiles.java
@@ -12,16 +12,29 @@
  */
 public class LauncherFiles {
 
-    public static final String SHARED_PREFS = "com.android.launcher3.prefs.xml";
+    private static final String XML = ".xml";
+
+    public static final String DEFAULT_WALLPAPER_THUMBNAIL = "default_thumb2.jpg";
+    public static final String DEFAULT_WALLPAPER_THUMBNAIL_OLD = "default_thumb.jpg";
     public static final String LAUNCHER_DB = "launcher.db";
-    public static final String LAUNCHER_PREFS = "launcher.preferences";
+    public static final String LAUNCHER_PREFERENCES = "launcher.preferences";
+    public static final String LAUNCHES_LOG = "launches.log";
+    public static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
+    public static final String STATS_LOG = "stats.log";
+    public static final String WALLPAPER_CROP_PREFERENCES_KEY =
+            WallpaperCropActivity.class.getName();
     public static final String WALLPAPER_IMAGES_DB = "saved_wallpaper_images.db";
     public static final String WIDGET_PREVIEWS_DB = "widgetpreviews.db";
 
     public static final List<String> ALL_FILES = Collections.unmodifiableList(Arrays.asList(
-            SHARED_PREFS,
+            DEFAULT_WALLPAPER_THUMBNAIL,
+            DEFAULT_WALLPAPER_THUMBNAIL_OLD,
             LAUNCHER_DB,
-            LAUNCHER_PREFS,
+            LAUNCHER_PREFERENCES,
+            LAUNCHES_LOG,
+            SHARED_PREFERENCES_KEY + XML,
+            STATS_LOG,
+            WALLPAPER_CROP_PREFERENCES_KEY + XML,
             WALLPAPER_IMAGES_DB,
             WIDGET_PREVIEWS_DB));
 }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 30a0337..17670d2 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -2241,7 +2241,7 @@
                                             // App restore has started. Update the flag
                                             appWidgetInfo.restoreStatus |=
                                                     LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
-                                        } else if (REMOVE_UNRESTORED_ICONS) {
+                                        } else if (REMOVE_UNRESTORED_ICONS && !isSafeMode) {
                                             Launcher.addDumpLog(TAG,
                                                     "Unrestored widget removed: " + component, true);
                                             itemsToRemove.add(id);
@@ -3534,17 +3534,6 @@
         }
     }
 
-    ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,
-            int cellX, int cellY, boolean notify) {
-        final ShortcutInfo info = infoFromShortcutIntent(context, data, null);
-        if (info == null) {
-            return null;
-        }
-        addItemToDatabase(context, info, container, screen, cellX, cellY, notify);
-
-        return info;
-    }
-
     /**
      * Attempts to find an AppWidgetProviderInfo that matches the given component.
      */
@@ -3560,7 +3549,7 @@
         return null;
     }
 
-    ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {
+    ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
@@ -3593,12 +3582,8 @@
         // users wouldn't get here without intent forwarding anyway.
         info.user = UserHandleCompat.myUserHandle();
         if (icon == null) {
-            if (fallbackIcon != null) {
-                icon = fallbackIcon;
-            } else {
-                icon = mIconCache.getDefaultIcon(info.user);
-                info.usingFallbackIcon = true;
-            }
+            icon = mIconCache.getDefaultIcon(info.user);
+            info.usingFallbackIcon = true;
         }
         info.setIcon(icon);
 
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 44ccb6c..9150dc0 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -31,12 +31,7 @@
 import android.content.Intent;
 import android.content.OperationApplicationException;
 import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
@@ -46,7 +41,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
-import android.os.Bundle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -58,11 +52,7 @@
 import com.android.launcher3.compat.UserManagerCompat;
 import com.android.launcher3.config.ProviderConfig;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
-import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -89,9 +79,6 @@
     static final String EMPTY_DATABASE_CREATED =
             "EMPTY_DATABASE_CREATED";
 
-    private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
-            "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
-
     private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
 
     private LauncherProviderChangeListener mListener;
@@ -160,12 +147,6 @@
         return db.insert(table, nullColumnHack, values);
     }
 
-    private static void deleteId(SQLiteDatabase db, long id) {
-        Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
-        SqlArguments args = new SqlArguments(uri, null, null);
-        db.delete(args.table, args.where, args.args);
-    }
-
     @Override
     public Uri insert(Uri uri, ContentValues initialValues) {
         SqlArguments args = new SqlArguments(uri);
@@ -325,7 +306,7 @@
         if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
             Log.d(TAG, "loading default workspace");
 
-            WorkspaceLoader loader = AutoInstallsLayout.get(getContext(),
+            AutoInstallsLayout loader = AutoInstallsLayout.get(getContext(),
                     mOpenHelper.mAppWidgetHost, mOpenHelper);
 
             if (loader == null) {
@@ -335,14 +316,15 @@
                     int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
                             "xml", partner.getPackageName());
                     if (workspaceResId != 0) {
-                        loader = new SimpleWorkspaceLoader(mOpenHelper, partnerRes, workspaceResId);
+                        loader = new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost,
+                                mOpenHelper, partnerRes, workspaceResId);
                     }
                 }
             }
 
             if (loader == null) {
-                loader = new SimpleWorkspaceLoader(mOpenHelper, getContext().getResources(),
-                        getDefaultWorkspaceResourceId());
+                loader = new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost,
+                        mOpenHelper, getContext().getResources(), getDefaultWorkspaceResourceId());
             }
 
             // Populate favorites table with initial favorites
@@ -360,11 +342,7 @@
     private static int getDefaultWorkspaceResourceId() {
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        if (LauncherAppState.isDisableAllApps()) {
-            return grid.defaultNoAllAppsLayoutId;
-        } else {
-            return grid.defaultLayoutId;
-        }
+        return grid.defaultLayoutId;
     }
 
     private static interface ContentValuesCallback {
@@ -390,38 +368,7 @@
     }
 
     private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
-        private static final String TAG_RESOLVE = "resolve";
-        private static final String TAG_FAVORITES = "favorites";
-        private static final String TAG_FAVORITE = "favorite";
-        private static final String TAG_APPWIDGET = "appwidget";
-        private static final String TAG_SHORTCUT = "shortcut";
-        private static final String TAG_FOLDER = "folder";
-        private static final String TAG_PARTNER_FOLDER = "partner-folder";
-        private static final String TAG_EXTRA = "extra";
-        private static final String TAG_INCLUDE = "include";
-
-        // Style attrs -- "Favorite"
-        private static final String ATTR_CLASS_NAME = "className";
-        private static final String ATTR_PACKAGE_NAME = "packageName";
-        private static final String ATTR_CONTAINER = "container";
-        private static final String ATTR_SCREEN = "screen";
-        private static final String ATTR_X = "x";
-        private static final String ATTR_Y = "y";
-        private static final String ATTR_SPAN_X = "spanX";
-        private static final String ATTR_SPAN_Y = "spanY";
-        private static final String ATTR_ICON = "icon";
-        private static final String ATTR_TITLE = "title";
-        private static final String ATTR_URI = "uri";
-
-        // Style attrs -- "Include"
-        private static final String ATTR_WORKSPACE = "workspace";
-
-        // Style attrs -- "Extra"
-        private static final String ATTR_KEY = "key";
-        private static final String ATTR_VALUE = "value";
-
         private final Context mContext;
-        private final PackageManager mPackageManager;
         private final AppWidgetHost mAppWidgetHost;
         private long mMaxItemId = -1;
         private long mMaxScreenId = -1;
@@ -431,7 +378,6 @@
         DatabaseHelper(Context context) {
             super(context, LauncherFiles.LAUNCHER_DB, null, DATABASE_VERSION);
             mContext = context;
-            mPackageManager = context.getPackageManager();
             mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
 
             // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
@@ -787,8 +733,8 @@
                 }
 
                 // Add default hotseat icons
-                loadFavorites(db, new SimpleWorkspaceLoader(this, mContext.getResources(),
-                        R.xml.update_workspace));
+                loadFavorites(db, new DefaultLayoutParser(mContext, mAppWidgetHost, this,
+                        mContext.getResources(), R.xml.update_workspace));
                 version = 9;
             }
 
@@ -1288,14 +1234,16 @@
                     try {
                         int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
                         values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
-                        if (appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,cn)) {
-                            return true;
+                        if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,cn)) {
+                            return false;
                         }
                     } catch (RuntimeException e) {
                         Log.e(TAG, "Failed to initialize external widget", e);
+                        return false;
                     }
+                } else {
+                    return false;
                 }
-                return false;
             }
 
             // Add screen id if not present
@@ -1353,31 +1301,7 @@
             return rank;
         }
 
-        private static final void beginDocument(XmlPullParser parser, String firstElementName)
-                throws XmlPullParserException, IOException {
-            int type;
-            while ((type = parser.next()) != XmlPullParser.START_TAG
-                    && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
-
-            if (type != XmlPullParser.START_TAG) {
-                throw new XmlPullParserException("No start tag found");
-            }
-
-            if (!parser.getName().equals(firstElementName)) {
-                throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
-                        ", expected " + firstElementName);
-            }
-        }
-
-        private static Intent buildMainIntent() {
-            Intent intent = new Intent(Intent.ACTION_MAIN, null);
-            intent.addCategory(Intent.CATEGORY_LAUNCHER);
-            return intent;
-        }
-
-        private int loadFavorites(SQLiteDatabase db, WorkspaceLoader loader) {
+        private int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
             ArrayList<Long> screenIds = new ArrayList<Long>();
             // TODO: Use multiple loaders with fall-back and transaction.
             int count = loader.loadLayout(db, screenIds);
@@ -1404,379 +1328,6 @@
             return count;
         }
 
-        /**
-         * Loads the default set of favorite packages from an xml file.
-         *
-         * @param db The database to write the values into
-         * @param filterContainerId The specific container id of items to load
-         * @param the set of screenIds which are used by the favorites
-         */
-        private int loadFavoritesRecursive(SQLiteDatabase db, Resources res, int workspaceResourceId,
-                ArrayList<Long> screenIds) {
-
-            ContentValues values = new ContentValues();
-            if (LOGD) Log.v(TAG, String.format("Loading favorites from resid=0x%08x", workspaceResourceId));
-
-            int count = 0;
-            try {
-                XmlResourceParser parser = res.getXml(workspaceResourceId);
-                beginDocument(parser, TAG_FAVORITES);
-
-                final int depth = parser.getDepth();
-
-                int type;
-                while (((type = parser.next()) != XmlPullParser.END_TAG ||
-                        parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
-
-                    if (type != XmlPullParser.START_TAG) {
-                        continue;
-                    }
-
-                    boolean added = false;
-                    final String name = parser.getName();
-
-                    if (TAG_INCLUDE.equals(name)) {
-
-                        final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
-
-                        if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s<include workspace=%08x>"),
-                                "", resId));
-
-                        if (resId != 0 && resId != workspaceResourceId) {
-                            // recursively load some more favorites, why not?
-                            count += loadFavoritesRecursive(db, res, resId, screenIds);
-                            added = false;
-                        } else {
-                            Log.w(TAG, String.format("Skipping <include workspace=0x%08x>", resId));
-                        }
-
-                        if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s</include>"), ""));
-                        continue;
-                    }
-
-                    // Assuming it's a <favorite> at this point
-                    long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
-                    String strContainer = getAttributeValue(parser, ATTR_CONTAINER);
-                    if (strContainer != null) {
-                        container = Long.valueOf(strContainer);
-                    }
-
-                    String screen = getAttributeValue(parser, ATTR_SCREEN);
-                    String x = getAttributeValue(parser, ATTR_X);
-                    String y = getAttributeValue(parser, ATTR_Y);
-
-                    values.clear();
-                    values.put(LauncherSettings.Favorites.CONTAINER, container);
-                    values.put(LauncherSettings.Favorites.SCREEN, screen);
-                    values.put(LauncherSettings.Favorites.CELLX, x);
-                    values.put(LauncherSettings.Favorites.CELLY, y);
-
-                    if (LOGD) {
-                        final String title = getAttributeValue(parser, ATTR_TITLE);
-                        final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
-                        final String something = title != null ? title : pkg;
-                        Log.v(TAG, String.format(
-                                ("%" + (2*(depth+1)) + "s<%s%s c=%d s=%s x=%s y=%s>"),
-                                "", name,
-                                (something == null ? "" : (" \"" + something + "\"")),
-                                container, screen, x, y));
-                    }
-
-                    if (TAG_FAVORITE.equals(name)) {
-                        long id = addAppShortcut(db, values, parser);
-                        added = id >= 0;
-                    } else if (TAG_APPWIDGET.equals(name)) {
-                        added = addAppWidget(parser, type, db, values);
-                    } else if (TAG_SHORTCUT.equals(name)) {
-                        long id = addUriShortcut(db, values, res, parser);
-                        added = id >= 0;
-                    } else if (TAG_RESOLVE.equals(name)) {
-                        // This looks through the contained favorites (or meta-favorites) and
-                        // attempts to add them as shortcuts in the fallback group's location
-                        // until one is added successfully.
-                        added = false;
-                        final int groupDepth = parser.getDepth();
-                        while ((type = parser.next()) != XmlPullParser.END_TAG ||
-                                parser.getDepth() > groupDepth) {
-                            if (type != XmlPullParser.START_TAG) {
-                                continue;
-                            }
-                            final String fallback_item_name = parser.getName();
-                            if (!added) {
-                                if (TAG_FAVORITE.equals(fallback_item_name)) {
-                                    final long id = addAppShortcut(db, values, parser);
-                                    added = id >= 0;
-                                } else {
-                                    Log.e(TAG, "Fallback groups can contain only favorites, found "
-                                            + fallback_item_name);
-                                }
-                            }
-                        }
-                    } else if (TAG_FOLDER.equals(name)) {
-                        // Folder contents are nested in this XML file
-                        added = loadFolder(db, values, res, parser);
-
-                    } else if (TAG_PARTNER_FOLDER.equals(name)) {
-                        // Folder contents come from an external XML resource
-                        final Partner partner = Partner.get(mPackageManager);
-                        if (partner != null) {
-                            final Resources partnerRes = partner.getResources();
-                            final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
-                                    "xml", partner.getPackageName());
-                            if (resId != 0) {
-                                final XmlResourceParser partnerParser = partnerRes.getXml(resId);
-                                beginDocument(partnerParser, TAG_FOLDER);
-                                added = loadFolder(db, values, partnerRes, partnerParser);
-                            }
-                        }
-                    }
-                    if (added) {
-                        long screenId = Long.parseLong(screen);
-                        // Keep track of the set of screens which need to be added to the db.
-                        if (!screenIds.contains(screenId) &&
-                                container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                            screenIds.add(screenId);
-                        }
-                        count++;
-                    }
-                }
-            } catch (XmlPullParserException e) {
-                Log.w(TAG, "Got exception parsing favorites.", e);
-            } catch (IOException e) {
-                Log.w(TAG, "Got exception parsing favorites.", e);
-            } catch (RuntimeException e) {
-                Log.w(TAG, "Got exception parsing favorites.", e);
-            }
-            return count;
-        }
-
-        /**
-         * Parse folder starting at current {@link XmlPullParser} location.
-         */
-        private boolean loadFolder(SQLiteDatabase db, ContentValues values, Resources res,
-                XmlResourceParser parser) throws IOException, XmlPullParserException {
-            final String title;
-            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
-            if (titleResId != 0) {
-                title = res.getString(titleResId);
-            } else {
-                title = mContext.getResources().getString(R.string.folder_name);
-            }
-
-            values.put(LauncherSettings.Favorites.TITLE, title);
-            long folderId = addFolder(db, values);
-            boolean added = folderId >= 0;
-
-            ArrayList<Long> folderItems = new ArrayList<Long>();
-
-            int type;
-            int folderDepth = parser.getDepth();
-            while ((type = parser.next()) != XmlPullParser.END_TAG ||
-                    parser.getDepth() > folderDepth) {
-                if (type != XmlPullParser.START_TAG) {
-                    continue;
-                }
-                final String tag = parser.getName();
-
-                final ContentValues childValues = new ContentValues();
-                childValues.put(LauncherSettings.Favorites.CONTAINER, folderId);
-
-                if (LOGD) {
-                    final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
-                    final String uri = getAttributeValue(parser, ATTR_URI);
-                    Log.v(TAG, String.format(("%" + (2*(folderDepth+1)) + "s<%s \"%s\">"), "",
-                            tag, uri != null ? uri : pkg));
-                }
-
-                if (TAG_FAVORITE.equals(tag) && folderId >= 0) {
-                    final long id = addAppShortcut(db, childValues, parser);
-                    if (id >= 0) {
-                        folderItems.add(id);
-                    }
-                } else if (TAG_SHORTCUT.equals(tag) && folderId >= 0) {
-                    final long id = addUriShortcut(db, childValues, res, parser);
-                    if (id >= 0) {
-                        folderItems.add(id);
-                    }
-                } else {
-                    throw new RuntimeException("Folders can contain only shortcuts");
-                }
-            }
-
-            // We can only have folders with >= 2 items, so we need to remove the
-            // folder and clean up if less than 2 items were included, or some
-            // failed to add, and less than 2 were actually added
-            if (folderItems.size() < 2 && folderId >= 0) {
-                // Delete the folder
-                deleteId(db, folderId);
-
-                // If we have a single item, promote it to where the folder
-                // would have been.
-                if (folderItems.size() == 1) {
-                    final ContentValues childValues = new ContentValues();
-                    copyInteger(values, childValues, LauncherSettings.Favorites.CONTAINER);
-                    copyInteger(values, childValues, LauncherSettings.Favorites.SCREEN);
-                    copyInteger(values, childValues, LauncherSettings.Favorites.CELLX);
-                    copyInteger(values, childValues, LauncherSettings.Favorites.CELLY);
-
-                    final long id = folderItems.get(0);
-                    db.update(TABLE_FAVORITES, childValues,
-                            LauncherSettings.Favorites._ID + "=" + id, null);
-                } else {
-                    added = false;
-                }
-            }
-            return added;
-        }
-
-        // A meta shortcut attempts to resolve an intent specified as a URI in the XML, if a
-        // logical choice for what shortcut should be used for that intent exists, then it is
-        // added. Otherwise add nothing.
-        private long addAppShortcutByUri(SQLiteDatabase db, ContentValues values,
-                String intentUri) {
-            Intent metaIntent;
-            try {
-                metaIntent = Intent.parseUri(intentUri, 0);
-            } catch (URISyntaxException e) {
-                Log.e(TAG, "Unable to add meta-favorite: " + intentUri, e);
-                return -1;
-            }
-
-            ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent,
-                    PackageManager.MATCH_DEFAULT_ONLY);
-            final List<ResolveInfo> appList = mPackageManager.queryIntentActivities(
-                    metaIntent, PackageManager.MATCH_DEFAULT_ONLY);
-
-            // Verify that the result is an app and not just the resolver dialog asking which
-            // app to use.
-            if (wouldLaunchResolverActivity(resolved, appList)) {
-                // If only one of the results is a system app then choose that as the default.
-                final ResolveInfo systemApp = getSingleSystemActivity(appList);
-                if (systemApp == null) {
-                    // There is no logical choice for this meta-favorite, so rather than making
-                    // a bad choice just add nothing.
-                    Log.w(TAG, "No preference or single system activity found for "
-                            + metaIntent.toString());
-                    return -1;
-                }
-                resolved = systemApp;
-            }
-            final ActivityInfo info = resolved.activityInfo;
-            final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName);
-            if (intent == null) {
-                return -1;
-            }
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
-            return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(), intent);
-        }
-
-        private ResolveInfo getSingleSystemActivity(List<ResolveInfo> appList) {
-            ResolveInfo systemResolve = null;
-            final int N = appList.size();
-            for (int i = 0; i < N; ++i) {
-                try {
-                    ApplicationInfo info = mPackageManager.getApplicationInfo(
-                            appList.get(i).activityInfo.packageName, 0);
-                    if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-                        if (systemResolve != null) {
-                            return null;
-                        } else {
-                            systemResolve = appList.get(i);
-                        }
-                    }
-                } catch (PackageManager.NameNotFoundException e) {
-                    Log.w(TAG, "Unable to get info about resolve results", e);
-                    return null;
-                }
-            }
-            return systemResolve;
-        }
-
-        private boolean wouldLaunchResolverActivity(ResolveInfo resolved,
-                List<ResolveInfo> appList) {
-            // If the list contains the above resolved activity, then it can't be
-            // ResolverActivity itself.
-            for (int i = 0; i < appList.size(); ++i) {
-                ResolveInfo tmp = appList.get(i);
-                if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
-                        && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        private long addAppShortcut(SQLiteDatabase db, ContentValues values,
-                XmlResourceParser parser) {
-            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
-            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
-            final String uri = getAttributeValue(parser, ATTR_URI);
-
-            if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) {
-                ActivityInfo info;
-                try {
-                    ComponentName cn;
-                    try {
-                        cn = new ComponentName(packageName, className);
-                        info = mPackageManager.getActivityInfo(cn, 0);
-                    } catch (PackageManager.NameNotFoundException nnfe) {
-                        String[] packages = mPackageManager.currentToCanonicalPackageNames(
-                                new String[] { packageName });
-                        cn = new ComponentName(packages[0], className);
-                        info = mPackageManager.getActivityInfo(cn, 0);
-                    }
-                    final Intent intent = buildMainIntent();
-                    intent.setComponent(cn);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
-                    return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(),
-                            intent);
-                } catch (PackageManager.NameNotFoundException e) {
-                    Log.w(TAG, "Unable to add favorite: " + packageName +
-                            "/" + className, e);
-                }
-                return -1;
-            } else if (!TextUtils.isEmpty(uri)) {
-                // If no component specified try to find a shortcut to add from the URI.
-                return addAppShortcutByUri(db, values, uri);
-            } else {
-                Log.e(TAG, "Skipping invalid <favorite> with no component or uri");
-                return -1;
-            }
-        }
-
-        private long addAppShortcut(SQLiteDatabase db, ContentValues values, String title,
-                Intent intent) {
-            long id = generateNewItemId();
-            values.put(Favorites.INTENT, intent.toUri(0));
-            values.put(Favorites.TITLE, title);
-            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
-            values.put(Favorites.SPANX, 1);
-            values.put(Favorites.SPANY, 1);
-            values.put(Favorites._ID, id);
-            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
-                return -1;
-            } else {
-                return id;
-            }
-        }
-
-        private long addFolder(SQLiteDatabase db, ContentValues values) {
-            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER);
-            values.put(Favorites.SPANX, 1);
-            values.put(Favorites.SPANY, 1);
-            long id = generateNewItemId();
-            values.put(Favorites._ID, id);
-            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) {
-                return -1;
-            } else {
-                return id;
-            }
-        }
-
         private ComponentName getSearchWidgetProvider() {
             SearchManager searchManager =
                     (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
@@ -1803,140 +1354,6 @@
             return null;
         }
 
-        private boolean addAppWidget(XmlResourceParser parser, int type,
-                SQLiteDatabase db, ContentValues values)
-                throws XmlPullParserException, IOException {
-
-            String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
-            String className = getAttributeValue(parser, ATTR_CLASS_NAME);
-
-            if (packageName == null || className == null) {
-                return false;
-            }
-
-            boolean hasPackage = true;
-            ComponentName cn = new ComponentName(packageName, className);
-            try {
-                mPackageManager.getReceiverInfo(cn, 0);
-            } catch (Exception e) {
-                String[] packages = mPackageManager.currentToCanonicalPackageNames(
-                        new String[] { packageName });
-                cn = new ComponentName(packages[0], className);
-                try {
-                    mPackageManager.getReceiverInfo(cn, 0);
-                } catch (Exception e1) {
-                    System.out.println("Can't find widget provider: " + className);
-                    hasPackage = false;
-                }
-            }
-
-            if (hasPackage) {
-                String spanX = getAttributeValue(parser, ATTR_SPAN_X);
-                String spanY = getAttributeValue(parser, ATTR_SPAN_Y);
-
-                values.put(Favorites.SPANX, spanX);
-                values.put(Favorites.SPANY, spanY);
-
-                // Read the extras
-                Bundle extras = new Bundle();
-                int widgetDepth = parser.getDepth();
-                while ((type = parser.next()) != XmlPullParser.END_TAG ||
-                        parser.getDepth() > widgetDepth) {
-                    if (type != XmlPullParser.START_TAG) {
-                        continue;
-                    }
-
-                    if (TAG_EXTRA.equals(parser.getName())) {
-                        String key = getAttributeValue(parser, ATTR_KEY);
-                        String value = getAttributeValue(parser, ATTR_VALUE);
-                        if (key != null && value != null) {
-                            extras.putString(key, value);
-                        } else {
-                            throw new RuntimeException("Widget extras must have a key and value");
-                        }
-                    } else {
-                        throw new RuntimeException("Widgets can contain only extras");
-                    }
-                }
-
-                return addAppWidget(db, values, cn, extras);
-            }
-
-            return false;
-        }
-
-        private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn,
-               Bundle extras) {
-            boolean allocatedAppWidgets = false;
-            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
-
-            try {
-                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
-
-                values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
-                values.put(Favorites.APPWIDGET_ID, appWidgetId);
-                values.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
-                values.put(Favorites._ID, generateNewItemId());
-                dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
-
-                allocatedAppWidgets = true;
-
-                // TODO: need to check return value
-                appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn);
-
-                // Send a broadcast to configure the widget
-                if (extras != null && !extras.isEmpty()) {
-                    Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
-                    intent.setComponent(cn);
-                    intent.putExtras(extras);
-                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
-                    mContext.sendBroadcast(intent);
-                }
-            } catch (RuntimeException ex) {
-                Log.e(TAG, "Problem allocating appWidgetId", ex);
-            }
-
-            return allocatedAppWidgets;
-        }
-
-        private long addUriShortcut(SQLiteDatabase db, ContentValues values, Resources res,
-                XmlResourceParser parser) {
-            final int iconResId = getAttributeResourceValue(parser, ATTR_ICON, 0);
-            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
-
-            Intent intent;
-            String uri = null;
-            try {
-                uri = getAttributeValue(parser, ATTR_URI);
-                intent = Intent.parseUri(uri, 0);
-            } catch (URISyntaxException e) {
-                Log.w(TAG, "Shortcut has malformed uri: " + uri);
-                return -1; // Oh well
-            }
-
-            if (iconResId == 0 || titleResId == 0) {
-                Log.w(TAG, "Shortcut is missing title or icon resource ID");
-                return -1;
-            }
-
-            long id = generateNewItemId();
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            values.put(Favorites.INTENT, intent.toUri(0));
-            values.put(Favorites.TITLE, res.getString(titleResId));
-            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_SHORTCUT);
-            values.put(Favorites.SPANX, 1);
-            values.put(Favorites.SPANY, 1);
-            values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
-            values.put(Favorites.ICON_PACKAGE, res.getResourcePackageName(iconResId));
-            values.put(Favorites.ICON_RESOURCE, res.getResourceName(iconResId));
-            values.put(Favorites._ID, id);
-
-            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
-                return -1;
-            }
-            return id;
-        }
-
         private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
             final ContentResolver resolver = mContext.getContentResolver();
             Cursor c = null;
@@ -2236,38 +1653,6 @@
         return selectWhere.toString();
     }
 
-    /**
-     * Return attribute value, attempting launcher-specific namespace first
-     * before falling back to anonymous attribute.
-     */
-    private static String getAttributeValue(XmlResourceParser parser, String attribute) {
-        String value = parser.getAttributeValue(
-                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
-        if (value == null) {
-            value = parser.getAttributeValue(null, attribute);
-        }
-        return value;
-    }
-
-    /**
-     * Return attribute resource value, attempting launcher-specific namespace
-     * first before falling back to anonymous attribute.
-     */
-    private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
-            int defaultValue) {
-        int value = parser.getAttributeResourceValue(
-                "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
-                defaultValue);
-        if (value == defaultValue) {
-            value = parser.getAttributeResourceValue(null, attribute, defaultValue);
-        }
-        return value;
-    }
-
-    private static void copyInteger(ContentValues from, ContentValues to, String key) {
-        to.put(key, from.getAsInteger(key));
-    }
-
     static class SqlArguments {
         public final String table;
         public final String where;
@@ -2299,29 +1684,4 @@
             }
         }
     }
-
-    static interface WorkspaceLoader {
-        /**
-         * @param screenIds A mutable list of screen its
-         * @return the number of workspace items added.
-         */
-        int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds);
-    }
-
-    private static class SimpleWorkspaceLoader implements WorkspaceLoader {
-        private final Resources mRes;
-        private final int mWorkspaceId;
-        private final DatabaseHelper mHelper;
-
-        SimpleWorkspaceLoader(DatabaseHelper helper, Resources res, int workspaceId) {
-            mHelper = helper;
-            mRes = res;
-            mWorkspaceId = workspaceId;
-        }
-
-        @Override
-        public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
-            return mHelper.loadFavoritesRecursive(db, mRes, mWorkspaceId, screenIds);
-        }
-    }
 }
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index d23a330..179c60a 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -41,9 +41,9 @@
     private final LauncherAppWidgetInfo mInfo;
     private final int mStartState;
     private final Intent mIconLookupIntent;
+    private final boolean mDisabledForSafeMode;
 
     private Bitmap mIcon;
-    private PreloadIconDrawable mDrawable;
 
     private Drawable mCenterDrawable;
     private Drawable mTopCornerDrawable;
@@ -53,11 +53,13 @@
     private final TextPaint mPaint;
     private Layout mSetupTextLayout;
 
-    public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info) {
+    public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
+            boolean disabledForSafeMode) {
         super(context);
         mInfo = info;
         mStartState = info.restoreStatus;
         mIconLookupIntent = new Intent().setComponent(info.providerName);
+        mDisabledForSafeMode = disabledForSafeMode;
 
         mPaint = new TextPaint();
         mPaint.setColor(0xFFFFFFFF);
@@ -106,14 +108,21 @@
             return;
         }
         mIcon = icon;
-        if (mDrawable != null) {
-            mDrawable.setCallback(null);
-            mDrawable = null;
+        if (mCenterDrawable != null) {
+            mCenterDrawable.setCallback(null);
+            mCenterDrawable = null;
         }
         if (mIcon != null) {
-            // The view displays two modes, one with a setup icon and another with a preload icon
-            // in the center.
-            if (isReadyForClickSetup()) {
+            // The view displays three modes,
+            //   1) App icon in the center
+            //   2) Preload icon in the center
+            //   3) Setup icon in the center and app icon in the top right corner.
+            if (mDisabledForSafeMode) {
+                FastBitmapDrawable disabledIcon = Utilities.createIconDrawable(mIcon);
+                disabledIcon.setGhostModeEnabled(true);
+                mCenterDrawable = disabledIcon;
+                mTopCornerDrawable = null;
+            } else if (isReadyForClickSetup()) {
                 mCenterDrawable = getResources().getDrawable(R.drawable.ic_setting);
                 mTopCornerDrawable = new FastBitmapDrawable(mIcon);
             } else {
@@ -123,8 +132,9 @@
                 }
 
                 FastBitmapDrawable drawable = Utilities.createIconDrawable(mIcon);
-                mDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
-                mDrawable.setCallback(this);
+                mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
+                mCenterDrawable.setCallback(this);
+                mTopCornerDrawable = null;
                 applyState();
             }
             mDrawableSizeChanged = true;
@@ -133,12 +143,12 @@
 
     @Override
     protected boolean verifyDrawable(Drawable who) {
-        return (who == mDrawable) || super.verifyDrawable(who);
+        return (who == mCenterDrawable) || super.verifyDrawable(who);
     }
 
     public void applyState() {
-        if (mDrawable != null) {
-            mDrawable.setLevel(Math.max(mInfo.installProgress, 0));
+        if (mCenterDrawable != null) {
+            mCenterDrawable.setLevel(Math.max(mInfo.installProgress, 0));
         }
     }
 
@@ -158,23 +168,30 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mDrawable != null) {
+        if (mCenterDrawable == null) {
+            // Nothing to draw
+            return;
+        }
+
+        if (mTopCornerDrawable == null) {
             if (mDrawableSizeChanged) {
+                int outset = (mCenterDrawable instanceof PreloadIconDrawable) ?
+                        ((PreloadIconDrawable) mCenterDrawable).getOutset() : 0;
                 int maxSize = LauncherAppState.getInstance().getDynamicGrid()
-                        .getDeviceProfile().iconSizePx + 2 * mDrawable.getOutset();
+                        .getDeviceProfile().iconSizePx + 2 * outset;
                 int size = Math.min(maxSize, Math.min(
                         getWidth() - getPaddingLeft() - getPaddingRight(),
                         getHeight() - getPaddingTop() - getPaddingBottom()));
 
                 mRect.set(0, 0, size, size);
-                mRect.inset(mDrawable.getOutset(), mDrawable.getOutset());
+                mRect.inset(outset, outset);
                 mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
-                mDrawable.setBounds(mRect);
+                mCenterDrawable.setBounds(mRect);
                 mDrawableSizeChanged = false;
             }
-
-            mDrawable.draw(canvas);
-        } else if ((mCenterDrawable != null) && (mTopCornerDrawable != null)) {
+            mCenterDrawable.draw(canvas);
+        } else  {
+            // Draw the top corner icon and "Setup" text is possible
             if (mDrawableSizeChanged) {
                 DeviceProfile grid = getDeviceProfile();
                 int iconSize = grid.iconSizePx;
diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java
index f3977e4..a879865 100644
--- a/src/com/android/launcher3/Stats.java
+++ b/src/com/android/launcher3/Stats.java
@@ -38,12 +38,10 @@
     public static final String EXTRA_CELLX = "cellX";
     public static final String EXTRA_CELLY = "cellY";
 
-    private static final String LOG_FILE_NAME = "launches.log";
     private static final int LOG_VERSION = 1;
     private static final int LOG_TAG_VERSION = 0x1;
     private static final int LOG_TAG_LAUNCH = 0x1000;
 
-    private static final String STATS_FILE_NAME = "stats.log";
     private static final int STATS_VERSION = 1;
     private static final int INITIAL_STATS_SIZE = 100;
 
@@ -69,7 +67,8 @@
 
         if (LOCAL_LAUNCH_LOG) {
             try {
-                mLog = new DataOutputStream(mLauncher.openFileOutput(LOG_FILE_NAME, Context.MODE_APPEND));
+                mLog = new DataOutputStream(mLauncher.openFileOutput(
+                        LauncherFiles.LAUNCHES_LOG, Context.MODE_APPEND));
                 mLog.writeInt(LOG_TAG_VERSION);
                 mLog.writeInt(LOG_VERSION);
             } catch (FileNotFoundException e) {
@@ -160,7 +159,8 @@
     private void saveStats() {
         DataOutputStream stats = null;
         try {
-            stats = new DataOutputStream(mLauncher.openFileOutput(STATS_FILE_NAME + ".tmp", Context.MODE_PRIVATE));
+            stats = new DataOutputStream(mLauncher.openFileOutput(
+                    LauncherFiles.STATS_LOG + ".tmp", Context.MODE_PRIVATE));
             stats.writeInt(STATS_VERSION);
             final int N = mHistogram.size();
             stats.writeInt(N);
@@ -170,8 +170,8 @@
             }
             stats.close();
             stats = null;
-            mLauncher.getFileStreamPath(STATS_FILE_NAME + ".tmp")
-                     .renameTo(mLauncher.getFileStreamPath(STATS_FILE_NAME));
+            mLauncher.getFileStreamPath(LauncherFiles.STATS_LOG + ".tmp")
+                     .renameTo(mLauncher.getFileStreamPath(LauncherFiles.STATS_LOG));
         } catch (FileNotFoundException e) {
             Log.e(TAG, "unable to create stats data: " + e);
         } catch (IOException e) {
@@ -190,7 +190,7 @@
         mHistogram = new ArrayList<Integer>(INITIAL_STATS_SIZE);
         DataInputStream stats = null;
         try {
-            stats = new DataInputStream(mLauncher.openFileInput(STATS_FILE_NAME));
+            stats = new DataInputStream(mLauncher.openFileInput(LauncherFiles.STATS_LOG));
             final int version = stats.readInt();
             if (version == STATS_VERSION) {
                 final int N = stats.readInt();
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 92d7c7d..9cedae0 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -638,7 +638,7 @@
             c.setBitmap(null);
         }
         // Render the icon
-        Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info));
+        Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info.activityInfo));
 
         int paddingTop = mContext.
                 getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 5f074c1..79d31cd 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1267,7 +1267,6 @@
             mCustomContentShowing = false;
             if (mCustomContentCallbacks != null) {
                 mCustomContentCallbacks.onHide();
-                mLauncher.resetQSBScroll();
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }
         }