Merge "Update code so it compiles on google3" into ub-now-porkchop
diff --git a/res/drawable-hdpi/quantum_panel.9.png b/res/drawable-hdpi/quantum_panel.9.png
index d86d7bc..a005e0b 100644
--- a/res/drawable-hdpi/quantum_panel.9.png
+++ b/res/drawable-hdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_dark.9.png b/res/drawable-hdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..057efd1
--- /dev/null
+++ b/res/drawable-hdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel.9.png b/res/drawable-mdpi/quantum_panel.9.png
index 061c80a..785f573 100644
--- a/res/drawable-mdpi/quantum_panel.9.png
+++ b/res/drawable-mdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_dark.9.png b/res/drawable-mdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..7837e48
--- /dev/null
+++ b/res/drawable-mdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel.9.png b/res/drawable-xhdpi/quantum_panel.9.png
index 8605cfd..5726fd2 100644
--- a/res/drawable-xhdpi/quantum_panel.9.png
+++ b/res/drawable-xhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_dark.9.png b/res/drawable-xhdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..8944a8f
--- /dev/null
+++ b/res/drawable-xhdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel.9.png b/res/drawable-xxhdpi/quantum_panel.9.png
index 9a1a79c..035cdc4 100644
--- a/res/drawable-xxhdpi/quantum_panel.9.png
+++ b/res/drawable-xxhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_dark.9.png b/res/drawable-xxhdpi/quantum_panel_dark.9.png
new file mode 100644
index 0000000..b74f1a6
--- /dev/null
+++ b/res/drawable-xxhdpi/quantum_panel_dark.9.png
Binary files differ
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index 007c536..03e433a 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -24,17 +24,30 @@
         android:clipChildren="false"
         android:orientation="vertical">
 
-        <com.android.launcher3.AppsCustomizePagedView
-            android:id="@+id/apps_customize_pane_content"
+        <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_weight="1"
-            launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
-            launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
-            launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
-            launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
-            launcher:maxGap="@dimen/workspace_max_gap"
-            launcher:pageIndicator="@+id/apps_customize_page_indicator" />
+            android:layout_weight="1">
+            <FrameLayout
+                android:id="@+id/fake_page_container"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" >
+                <FrameLayout
+                android:id="@+id/fake_page"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+            </FrameLayout>
+            <com.android.launcher3.AppsCustomizePagedView
+                android:id="@+id/apps_customize_pane_content"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
+                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
+                launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
+                launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
+                launcher:maxGap="@dimen/workspace_max_gap"
+                launcher:pageIndicator="@+id/apps_customize_page_indicator" />
+        </FrameLayout>
         <include
             android:id="@+id/apps_customize_page_indicator"
             layout="@layout/page_indicator"
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
index 7c98b4a..e299b32 100644
--- a/res/layout/apps_customize_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -25,24 +25,45 @@
     android:background="@drawable/focusable_view_bg"
     android:focusable="true">
 
-    <!-- The preview of the widget or shortcut. -->
-    <com.android.launcher3.PagedViewWidgetImageView
-        android:id="@+id/widget_preview"
-        style="@style/PagedViewWidgetImageView"
+    <LinearLayout
+        android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:paddingTop="@dimen/app_widget_preview_padding_top"
-        android:paddingEnd="@dimen/app_widget_preview_padding_right"
-        android:paddingRight="@dimen/app_widget_preview_padding_right"
-        android:scaleType="matrix"
-        android:background="@drawable/screenpanel" />
+        android:layout_weight="1">
+        <FrameLayout
+            android:id="@+id/left_border"
+            android:layout_width="1dp"
+            android:layout_height="match_parent"
+            android:background="@color/widget_text_panel"
+            android:visibility="gone" />
+
+        <!-- The preview of the widget or shortcut. -->
+        <com.android.launcher3.PagedViewWidgetImageView
+            android:id="@+id/widget_preview"
+            style="@style/PagedViewWidgetImageView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:paddingTop="@dimen/app_widget_preview_padding_top"
+            android:paddingEnd="@dimen/app_widget_preview_padding_right"
+            android:paddingRight="@dimen/app_widget_preview_padding_right"
+            android:scaleType="matrix" />
+        <FrameLayout
+            android:id="@+id/right_border"
+            android:layout_width="1dp"
+            android:layout_height="match_parent"
+            android:background="@color/widget_text_panel"
+            android:visibility="gone" />
+    </LinearLayout>
+
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/app_widget_preview_label_margin_top"
-        android:layout_marginStart="@dimen/app_widget_preview_label_margin_left"
-        android:layout_marginEnd="@dimen/app_widget_preview_label_margin_right"
+        android:paddingTop="@dimen/app_widget_preview_label_vertical_padding"
+        android:paddingBottom="@dimen/app_widget_preview_label_vertical_padding"
+        android:paddingLeft="@dimen/app_widget_preview_label_horizontal_padding"
+        android:paddingRight="@dimen/app_widget_preview_label_horizontal_padding"
+        android:background="@color/widget_text_panel"
         android:orientation="horizontal">
         <!-- The name of the widget. -->
         <TextView xmlns:android="http://schemas.android.com/apk/res/android"
@@ -56,7 +77,7 @@
             android:fadingEdge="horizontal"
 
             android:textColor="#FFFFFFFF"
-            android:textSize="13sp"
+            android:textSize="12sp"
             android:textAlignment="viewStart"
             android:fontFamily="sans-serif-condensed"
             android:shadowRadius="2.0"
@@ -73,7 +94,7 @@
             android:layout_weight="0"
             android:gravity="start"
 
-            android:textColor="#FFAAAAAA"
+            android:textColor="#FFFFFFFF"
             android:textSize="12sp"
             android:fontFamily="sans-serif-condensed"
             android:shadowRadius="2.0"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f3bfcec..12fa3cd 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -98,11 +98,6 @@
         <!-- A spacing override for the icons within a page -->
         <attr name="pageLayoutWidthGap" format="dimension" />
         <attr name="pageLayoutHeightGap" format="dimension" />
-        <!-- The padding of the pages that are dynamically created per page -->
-        <attr name="pageLayoutPaddingTop" format="dimension" />
-        <attr name="pageLayoutPaddingBottom" format="dimension" />
-        <attr name="pageLayoutPaddingLeft" format="dimension" />
-        <attr name="pageLayoutPaddingRight" format="dimension" />
 
         <!-- The page indicator for this workspace -->
         <attr name="pageIndicator" format="reference" />
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 27a5b61..41f3892 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -36,6 +36,7 @@
     <color name="quantum_panel_text_shadow_color">#FFC4C4C4</color>
     <color name="folder_items_glow_color">#FFCCCCCC</color>
     <color name="outline_color">#FFFFFFFF</color>
-    
+    <color name="widget_text_panel">#FF374248</color>
+
     <color name="first_run_cling_circle_background_color">#64b1ea</color>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 3a862c5..a16f265 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -31,7 +31,8 @@
 
     <!-- Fade/zoom in/out duration & scale in the AllApps transition.
          Note: This should be less than the workspaceShrinkTime as they happen together. -->
-    <integer name="config_appsCustomizeRevealTime">350</integer>
+    <integer name="config_appsCustomizeRevealTime">220</integer>
+    <integer name="config_appsCustomizeItemsAlphaStagger">60</integer>
     <integer name="config_appsCustomizeZoomInTime">350</integer>
     <integer name="config_appsCustomizeZoomOutTime">600</integer>
     <integer name="config_appsCustomizeZoomScaleFactor">7</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8e561cf..893d7c0 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -62,7 +62,7 @@
     <dimen name="apps_customize_tab_bar_height">52dp</dimen>
     <dimen name="apps_customize_tab_bar_margin_top">0dp</dimen>
     <dimen name="app_icon_size">48dp</dimen>
-    <dimen name="apps_customize_horizontal_padding">4dp</dimen>
+    <dimen name="apps_customize_horizontal_padding">0dp</dimen>
 
     <!-- The AppsCustomize page indicator -->
     <dimen name="apps_customize_page_indicator_height">12dp</dimen>
@@ -89,9 +89,8 @@
     <dimen name="app_widget_preview_padding_left">16dp</dimen>
     <dimen name="app_widget_preview_padding_right">16dp</dimen>
     <dimen name="app_widget_preview_padding_top">32dp</dimen>
-    <dimen name="app_widget_preview_label_margin_top">4dp</dimen>
-    <dimen name="app_widget_preview_label_margin_left">2dp</dimen>
-    <dimen name="app_widget_preview_label_margin_right">2dp</dimen>
+    <dimen name="app_widget_preview_label_vertical_padding">8dp</dimen>
+    <dimen name="app_widget_preview_label_horizontal_padding">8dp</dimen>
 
     <!-- Padding applied to shortcut previews -->
     <dimen name="shortcut_preview_padding_left">0dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 780dcd2..286e04f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -193,9 +193,12 @@
     <!-- Text to show user in place of a gadget when we can't display it properly -->
     <string name="gadget_error_text">Problem loading widget</string>
 
-    <!-- Text to show user in place of a gadget when it is not yet ready/initialized. -->
+    <!-- Text to show user in place of a gadget when it is not yet ready. -->
     <string name="gadget_pending_text" translatable="false">Widget not ready</string>
 
+    <!-- Text to show user in place of a gadget when it is not yet initialized. -->
+    <string name="gadget_setup_text" translatable="false">Setup widget</string>
+
     <!-- Text to inform the user that they can't uninstall a system application -->
     <string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
 
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 80cb52d..880aaf1 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -46,17 +46,21 @@
             Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
 
             final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
+            final int state;
+            if (LauncherModel.isValidProvider(provider)) {
+                state = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+            } else {
+                state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+            }
 
             ContentValues values = new ContentValues();
             values.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]);
-            values.put(LauncherSettings.Favorites.RESTORED, LauncherModel.isValidProvider(provider)
-                    ? LauncherAppWidgetInfo.RESTORE_COMPLETED
-                            : LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING);
+            values.put(LauncherSettings.Favorites.RESTORED, state);
 
             String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) };
 
             int result = cr.update(Favorites.CONTENT_URI, values,
-                    "appWidgetId=? and restored=1", widgetIdParams);
+                    "appWidgetId=? and (restored & 1) = 1", widgetIdParams);
             if (result == 0) {
                 Cursor cursor = cr.query(Favorites.CONTENT_URI,
                         new String[] {Favorites.APPWIDGET_ID},
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 0e99696..e0543ce 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -148,6 +148,8 @@
         LauncherTransitionable {
     static final String TAG = "AppsCustomizePagedView";
 
+    private static Rect sTmpRect = new Rect();
+
     /**
      * The different content types that this paged view can show.
      */
@@ -183,7 +185,6 @@
     // Dimens
     private int mContentWidth, mContentHeight;
     private int mWidgetCountX, mWidgetCountY;
-    private int mWidgetWidthGap, mWidgetHeightGap;
     private PagedViewCellLayout mWidgetSpacingLayout;
     private int mNumAppsPages;
     private int mNumWidgetPages;
@@ -195,7 +196,7 @@
     private static float TRANSITION_SCALE_FACTOR = 0.74f;
     private static float TRANSITION_PIVOT = 0.65f;
     private static float TRANSITION_MAX_ROTATION = 22;
-    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+    private static final boolean PERFORM_OVERSCROLL_ROTATION = false;
     private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
     private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
 
@@ -213,6 +214,7 @@
     int mWidgetLoadingId = -1;
     PendingAddWidgetInfo mCreateWidgetInfo = null;
     private boolean mDraggingWidget = false;
+    boolean mPageBackgroundsVisible;
 
     private Toast mWidgetInstructionToast;
 
@@ -223,8 +225,6 @@
     private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
         new ArrayList<Runnable>();
 
-    private Rect mTmpRect = new Rect();
-
     WidgetPreviewLoader mWidgetPreviewLoader;
 
     private boolean mInBulkBind;
@@ -244,7 +244,6 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mWidgetWidthGap = mWidgetHeightGap = grid.edgeMarginPx;
         mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
         mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
         mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0);
@@ -284,8 +283,9 @@
     void setAllAppsPadding(Rect r) {
         mAllAppsPadding.set(r);
     }
+
     void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) {
-        mPageLayoutPaddingBottom = pageIndicatorHeight;
+        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), pageIndicatorHeight);
     }
 
     WidgetPreviewLoader getWidgetPreviewLoader() {
@@ -364,8 +364,6 @@
         // use for each page
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
-                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
         mCellCountX = (int) grid.allAppsNumCols;
         mCellCountY = (int) grid.allAppsNumRows;
         updatePageCounts();
@@ -540,26 +538,26 @@
         mLauncher.getWorkspace().beginDragShared(v, this);
     }
 
-    Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
+    static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
         Bundle options = null;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, mTmpRect);
-            Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(mLauncher,
+            AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, sTmpRect);
+            Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher,
                     info.componentName, null);
 
-            float density = getResources().getDisplayMetrics().density;
+            float density = launcher.getResources().getDisplayMetrics().density;
             int xPaddingDips = (int) ((padding.left + padding.right) / density);
             int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
 
             options = new Bundle();
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
-                    mTmpRect.left - xPaddingDips);
+                    sTmpRect.left - xPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
-                    mTmpRect.top - yPaddingDips);
+                    sTmpRect.top - yPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
-                    mTmpRect.right - xPaddingDips);
+                    sTmpRect.right - xPaddingDips);
             options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
-                    mTmpRect.bottom - yPaddingDips);
+                    sTmpRect.bottom - yPaddingDips);
         }
         return options;
     }
@@ -1001,14 +999,26 @@
         setVisibilityOnChildren(layout, View.GONE);
         int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
-        layout.setMinimumWidth(getPageContentWidth());
         layout.measure(widthSpec, heightSpec);
-        layout.setPadding(mAllAppsPadding.left, mAllAppsPadding.top, mAllAppsPadding.right,
-                mAllAppsPadding.bottom);
-        setVisibilityOnChildren(layout, View.VISIBLE);
 
-        Resources res = getContext().getResources();
-        layout.setBackground(res.getDrawable(R.drawable.quantum_panel));
+        Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel);
+        if (bg != null) {
+            layout.setBackground(bg);
+            bg.setVisible(mPageBackgroundsVisible, false);
+        }
+
+        setVisibilityOnChildren(layout, View.VISIBLE);
+    }
+
+    public void setPageBackgroundsVisible(boolean visible) {
+        mPageBackgroundsVisible = visible;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            Drawable bg = getChildAt(i).getBackground();
+            if (bg != null) {
+                bg.setVisible(visible, false);
+            }
+        }
     }
 
     public void syncAppsPageItems(int page, boolean immediate) {
@@ -1153,21 +1163,23 @@
         // immediately after syncing, we don't have a proper width.
         int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
-        layout.setMinimumWidth(getPageContentWidth());
+        layout.setBackground(getContext().getResources().getDrawable(R.drawable.quantum_panel_dark));
         layout.measure(widthSpec, heightSpec);
     }
 
     public void syncWidgetPageItems(final int page, final boolean immediate) {
         int numItemsPerPage = mWidgetCountX * mWidgetCountY;
 
+        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
+
         // Calculate the dimensions of each cell we are giving to each widget
         final ArrayList<Object> items = new ArrayList<Object>();
-        int contentWidth = mContentWidth;
-        final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft - mPageLayoutPaddingRight
-                - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
-        int contentHeight = mContentHeight;
-        final int cellHeight = ((contentHeight - mPageLayoutPaddingTop - mPageLayoutPaddingBottom
-                - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);
+        int contentWidth = mContentWidth - getPaddingLeft() - getPaddingRight()
+                - layout.getPaddingLeft() - layout.getPaddingRight();
+        final int cellWidth = contentWidth / mWidgetCountX;
+        int contentHeight = mContentHeight - getPaddingTop() - getPaddingBottom()
+                - layout.getPaddingTop() - layout.getPaddingBottom();
+        final int cellHeight = contentHeight / mWidgetCountY;
 
         // Prepare the set of widgets to load previews for in the background
         int offset = page * numItemsPerPage;
@@ -1176,7 +1188,6 @@
         }
 
         // Prepopulate the pages with the other widget info, and fill in the previews later
-        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
         layout.setColumnCount(layout.getCellCountX());
         for (int i = 0; i < items.size(); ++i) {
             Object rawInfo = items.get(i);
@@ -1217,14 +1228,22 @@
             // Layout each widget
             int ix = i % mWidgetCountX;
             int iy = i / mWidgetCountX;
+
+            if (ix > 0) {
+                View border = widget.findViewById(R.id.left_border);
+                border.setVisibility(View.VISIBLE);
+            }
+            if (ix < mWidgetCountX - 1) {
+                View border = widget.findViewById(R.id.right_border);
+                border.setVisibility(View.VISIBLE);
+            }
+
             GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
                     GridLayout.spec(iy, GridLayout.START),
                     GridLayout.spec(ix, GridLayout.TOP));
             lp.width = cellWidth;
             lp.height = cellHeight;
             lp.setGravity(Gravity.TOP | Gravity.START);
-            if (ix > 0) lp.leftMargin = mWidgetWidthGap;
-            if (iy > 0) lp.topMargin = mWidgetHeightGap;
             layout.addView(widget, lp);
         }
 
@@ -1438,24 +1457,6 @@
                         v.setRotationY(0f);
                     }
                 }
-
-                // TODO: clean this up
-                alpha = 1;
-                translationX = 0;
-                scale = 1;
-
-                v.setTranslationX(translationX);
-                v.setScaleX(scale);
-                v.setScaleY(scale);
-                v.setAlpha(alpha);
-
-                // If the view has 0 alpha, we set it to be invisible so as to prevent
-                // it from accepting touches
-                if (alpha == 0) {
-                    v.setVisibility(INVISIBLE);
-                } else if (v.getVisibility() != VISIBLE) {
-                    v.setVisibility(VISIBLE);
-                }
             }
         }
 
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
index 283f4ed..629bcdb 100644
--- a/src/com/android/launcher3/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher3/AppsCustomizeTabHost.java
@@ -181,9 +181,6 @@
     @Override
     public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
         mPagedView.onLauncherTransitionStart(l, animated, toWorkspace);
-        if (animated && !Utilities.isLmp()) {
-            enableAndBuildHardwareLayer();
-        }
     }
 
     @Override
@@ -195,9 +192,6 @@
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
         mPagedView.onLauncherTransitionEnd(l, animated, toWorkspace);
         mInTransition = false;
-        if (animated && !Utilities.isLmp()) {
-            setLayerType(LAYER_TYPE_NONE, null);
-        }
 
         if (!toWorkspace) {
             // Make sure adjacent pages are loaded (we wait until after the transition to
@@ -241,20 +235,4 @@
             throw new RuntimeException("Failed; can't get z-order of views");
         }
     }
-
-    private void enableAndBuildHardwareLayer() {
-        // isHardwareAccelerated() checks if we're attached to a window and if that
-        // window is HW accelerated-- we were sometimes not attached to a window
-        // and buildLayer was throwing an IllegalStateException
-        if (isHardwareAccelerated()) {
-            // Turn on hardware layers for performance
-            setLayerType(LAYER_TYPE_HARDWARE, null);
-
-            // force building the layer, so you don't get a blip early in an animation
-            // when the layer is created layer
-            buildLayer();
-        }
-    }
-
-
 }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c0f5054..018fcfc 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -775,6 +775,11 @@
 
             AppsCustomizePagedView pagedView = (AppsCustomizePagedView)
                     host.findViewById(R.id.apps_customize_pane_content);
+
+            FrameLayout fakePageContainer = (FrameLayout)
+                    host.findViewById(R.id.fake_page_container);
+            FrameLayout fakePage = (FrameLayout) host.findViewById(R.id.fake_page);
+
             padding = new Rect();
             if (pagedView != null) {
                 // Constrain the dimensions of all apps so that it does not span the full width
@@ -790,16 +795,24 @@
                 if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) {
                     padding.left = padding.right = gridPaddingLR;
                 }
+
                 // The icons are centered, so we can't just offset by the page indicator height
                 // because the empty space will actually be pageIndicatorHeight + paddingTB
                 padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB);
-                pagedView.setAllAppsPadding(padding);
+
                 pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight);
+                fakePage.setBackground(res.getDrawable(R.drawable.quantum_panel));
 
                 // Horizontal padding for the whole paged view
-                int pagedViewPadding =
+                int pagedFixedViewPadding =
                         res.getDimensionPixelSize(R.dimen.apps_customize_horizontal_padding);
-                pagedView.setPadding(pagedViewPadding, 0, pagedViewPadding, 0);
+
+                padding.left += pagedFixedViewPadding;
+                padding.right += pagedFixedViewPadding;
+
+                pagedView.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+                fakePageContainer.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+
             }
         }
 
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index c726fb4..8f96f74 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -124,6 +124,12 @@
     }
 
     ItemInfo(ItemInfo info) {
+        copyFrom(info);
+        // tempdebug:
+        LauncherModel.checkItemInfo(this);
+    }
+
+    public void copyFrom(ItemInfo info) {
         id = info.id;
         cellX = info.cellX;
         cellY = info.cellY;
@@ -134,8 +140,6 @@
         container = info.container;
         user = info.user;
         contentDescription = info.contentDescription;
-        // tempdebug:
-        LauncherModel.checkItemInfo(this);
     }
 
     public Intent getIntent() {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0ab665d..5eedc8a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -65,7 +65,6 @@
 import android.os.Message;
 import android.os.StrictMode;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.speech.RecognizerIntent;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
@@ -92,7 +91,9 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Advanceable;
 import android.widget.FrameLayout;
@@ -153,6 +154,7 @@
     private static final int REQUEST_PICK_WALLPAPER = 10;
 
     private static final int REQUEST_BIND_APPWIDGET = 11;
+    private static final int REQUEST_RECONFIGURE_APPWIDGET = 12;
 
     /**
      * IntentStarter uses request codes starting with this. This must be greater than all activity
@@ -752,6 +754,9 @@
             case REQUEST_CREATE_APPWIDGET:
                 completeAddAppWidget(args.appWidgetId, args.container, screenId, null, null);
                 break;
+            case REQUEST_RECONFIGURE_APPWIDGET:
+                completeRestoreAppWidget(args.appWidgetId);
+                break;
         }
         // Before adding this resetAddInfo(), after a shortcut was added to a workspace screen,
         // if you turned the screen off and then back while in All Apps, Launcher would not
@@ -854,6 +859,21 @@
             return;
         }
 
+        if (requestCode == REQUEST_RECONFIGURE_APPWIDGET) {
+            if (resultCode == RESULT_OK) {
+                // Update the widget view.
+                PendingAddArguments args = preparePendingAddArgs(requestCode, data,
+                        pendingAddWidgetId, mPendingAddInfo);
+                if (workspaceLocked) {
+                    sPendingAddItem = args;
+                } else {
+                    completeAdd(args);
+                }
+            }
+            // Leave the widget in the pending state if the user canceled the configure.
+            return;
+        }
+
         // The pattern used here is that a user PICKs a specific application,
         // which, depending on the target, might need to CREATE the actual target.
 
@@ -2446,6 +2466,10 @@
             }
         } else if (v == mAllAppsButton) {
             onClickAllAppsButton(v);
+        } else if (tag instanceof LauncherAppWidgetInfo) {
+            if (v instanceof PendingAppWidgetHostView) {
+                onClickPendingWidget((PendingAppWidgetHostView) v);
+            }
         }
     }
 
@@ -2454,6 +2478,27 @@
     }
 
     /**
+     * Event handler for the app widget view which has not fully restored.
+     */
+    public void onClickPendingWidget(PendingAppWidgetHostView v) {
+        if (v.isReadyForClickSetup()) {
+            LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
+            int widgetId = info.appWidgetId;
+            AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
+            if (appWidgetInfo != null) {
+                mPendingAddWidgetInfo = appWidgetInfo;
+                mPendingAddInfo.copyFrom(info);
+                mPendingAddWidgetId = widgetId;
+
+                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+                intent.setComponent(appWidgetInfo.configure);
+                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, info.appWidgetId);
+                Utilities.startActivityForResultSafely(this, intent, REQUEST_RECONFIGURE_APPWIDGET);
+            }
+        }
+    }
+
+    /**
      * Event handler for the search button
      *
      * @param v The view that was clicked.
@@ -3065,16 +3110,6 @@
         return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE);
     }
 
-    /**
-     * Helper method for the cameraZoomIn/cameraZoomOut animations
-     * @param view The view being animated
-     * @param scaleFactor The scale factor used for the zoom
-     */
-    private void setPivotsForZoom(View view, float scaleFactor) {
-        view.setPivotX(view.getWidth() / 2.0f);
-        view.setPivotY(view.getHeight() / 2.0f);
-    }
-
     private void setWorkspaceBackground(boolean workspace) {
         mLauncherView.setBackground(workspace ?
                 mWorkspaceBackgroundDrawable : null);
@@ -3185,6 +3220,8 @@
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
         final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
         final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
+        final int itemsAlphaStagger =
+                res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
 
         final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
         final View fromView = mWorkspace;
@@ -3192,8 +3229,6 @@
         final int startDelay =
                 res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
 
-        setPivotsForZoom(toView, scale);
-
         Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ?
                 Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN;
         Animator workspaceAnim =
@@ -3205,147 +3240,104 @@
         }
 
         if (animated) {
-            if (!material) {
-                toView.setScaleX(scale);
-                toView.setScaleY(scale);
-                final LauncherViewPropertyAnimator scaleAnim =
-                        new LauncherViewPropertyAnimator(toView);
-                scaleAnim.
-                    scaleX(1f).scaleY(1f).
-                    setDuration(duration).
-                    setInterpolator(new Workspace.ZoomOutInterpolator());
+            mStateAnimation = LauncherAnimUtils.createAnimatorSet();
 
-                toView.setVisibility(View.VISIBLE);
-                toView.setAlpha(0f);
-                final ObjectAnimator alphaAnim = LauncherAnimUtils
-                    .ofFloat(toView, "alpha", 0f, 1f)
-                    .setDuration(fadeDuration);
-                alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
-                alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animation) {
-                        if (animation == null) {
-                            throw new RuntimeException("animation is null");
-                        }
-                        float t = (Float) animation.getAnimatedValue();
-                        dispatchOnLauncherTransitionStep(fromView, t);
-                        dispatchOnLauncherTransitionStep(toView, t);
-                    }
-                });
+            final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                    toView.findViewById(R.id.apps_customize_pane_content);
 
-                // toView should appear right at the end of the workspace shrink
-                // animation
-                mStateAnimation = LauncherAnimUtils.createAnimatorSet();
-                mStateAnimation.play(scaleAnim).after(startDelay);
-                mStateAnimation.play(alphaAnim).after(startDelay);
+            final View page = content.getPageAt(content.getCurrentPage());
+            final View revealView = toView.findViewById(R.id.fake_page);
 
-                mStateAnimation.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationStart(Animator animation) {
-                        // Prepare the position
-                        toView.setTranslationX(0.0f);
-                        toView.setTranslationY(0.0f);
-                        toView.setVisibility(View.VISIBLE);
-                        toView.bringToFront();
-                    }
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        dispatchOnLauncherTransitionEnd(fromView, animated, false);
-                        dispatchOnLauncherTransitionEnd(toView, animated, false);
-
-                        // Hide the search bar
-                        if (mSearchDropTargetBar != null) {
-                            mSearchDropTargetBar.hideSearchBar(false);
-                        }
-                    }
-                });
+            if (contentType == AppsCustomizePagedView.ContentType.Widgets) {
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
             } else {
-                int width = toView.getMeasuredWidth();
-                int height = toView.getMeasuredHeight();
-                float revealRadius = (float) Math.sqrt((width * width) / 4 + height * height);
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
+            }
 
-                mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+            // Hide the real page background, and swap in the fake one
+            revealView.setVisibility(View.VISIBLE);
+            content.setPageBackgroundsVisible(false);
 
-                AppsCustomizePagedView content = (AppsCustomizePagedView)
-                        toView.findViewById(R.id.apps_customize_pane_content);
+            int width = revealView.getMeasuredWidth();
+            int height = revealView.getMeasuredHeight();
 
-                View page = content.getPageAt(content.getCurrentPage());
-                View revealView = content;
+            float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
+            float yDrift = height / 2f;
 
-                float yDrift = height / 2f - 400;
+            revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", 0.4f, 1f);
+            PropertyValuesHolder panelDrift =
+                    PropertyValuesHolder.ofFloat("translationY", yDrift, 0f);
 
-                LauncherViewPropertyAnimator panelAlphaAndDrift =
-                        new LauncherViewPropertyAnimator(revealView);
-                revealView.setTranslationY(yDrift);
-                revealView.setAlpha(0.3f);
-                panelAlphaAndDrift.alpha(1)
-                    .translationY(0)
-                    .setDuration(revealDuration)
-                    .setInterpolator(new LogDecelerateInterpolator(100, 0));
+            ObjectAnimator panelAlphaAndDrift =
+                    ObjectAnimator.ofPropertyValuesHolder(revealView, panelAlpha, panelDrift);
+            panelAlphaAndDrift.setDuration(revealDuration);
+            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
 
-                mStateAnimation.play(panelAlphaAndDrift);
+            mStateAnimation.play(panelAlphaAndDrift);
 
-                if (page instanceof CellLayout) {
-                    CellLayout cellLayout = (CellLayout) page;
-                    cellLayout.enableHardwareLayer(true);
+            if (page != null) {
+                page.setVisibility(View.VISIBLE);
+                page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 
-                    View iconsView = cellLayout.getShortcutsAndWidgets();
-                    iconsView.setAlpha(0f);
+                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0);
+                pageDrift.setDuration(revealDuration);
+                pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                mStateAnimation.play(pageDrift);
 
-                    LauncherViewPropertyAnimator iconsAlpha =
-                            new LauncherViewPropertyAnimator(iconsView);
-                    iconsAlpha.alpha(1f)
-                        .setDuration(revealDuration - 100)
-                        .setInterpolator(new LogDecelerateInterpolator(100, 0));
-                    mStateAnimation.play(iconsAlpha);
-                }
+                // TODO (adamcohen): remove this 0.01f hack once fw is fixed
+                // it's there to work around a framework bug (16918357)
+                page.setAlpha(0.01f);
+                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, "alpha", 0.01f, 1f);
+                itemsAlpha.setDuration(revealDuration);
+                itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+                itemsAlpha.setStartDelay(itemsAlphaStagger);
+                mStateAnimation.play(itemsAlpha);
+            }
 
-                View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator);
-                pageIndicators.setAlpha(0f);
-                final LauncherViewPropertyAnimator indicatorsAlpha =
-                        new LauncherViewPropertyAnimator(pageIndicators);
-                indicatorsAlpha.alpha(1f);
-                indicatorsAlpha.setDuration(revealDuration);
-                mStateAnimation.play(indicatorsAlpha);
+            View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator);
+            pageIndicators.setAlpha(0.01f);
+            ObjectAnimator indicatorsAlpha =
+                    ObjectAnimator.ofFloat(pageIndicators, "alpha", 1f);
+            indicatorsAlpha.setDuration(revealDuration);
+            mStateAnimation.play(indicatorsAlpha);
 
-                width = revealView.getMeasuredWidth();
-
-                Animator reveal =
+            if (material) {
+                ValueAnimator reveal = (ValueAnimator)
                         ViewAnimationUtils.createCircularReveal(revealView, width / 2,
-                                height / 2 + 100, 0f, revealRadius);
+                                height / 2, 0f, revealRadius);
                 reveal.setDuration(revealDuration);
                 reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
-
-                toView.setTranslationX(0);
-                toView.setTranslationY(0);
-                toView.setAlpha(1f);
-                // toView should appear right at the end of the workspace shrink
-                // animation
                 mStateAnimation.play(reveal);
-
-                reveal.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationStart(Animator animation) {
-                        // Prepare the position
-                        toView.bringToFront();
-                        toView.setVisibility(View.VISIBLE);
-                    }
-                });
-
-                mStateAnimation.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        dispatchOnLauncherTransitionEnd(fromView, animated, false);
-                        dispatchOnLauncherTransitionEnd(toView, animated, false);
-
-                        // Hide the search bar
-                        if (mSearchDropTargetBar != null) {
-                            mSearchDropTargetBar.hideSearchBar(false);
-                        }
-                    }
-                });
             }
 
+            mStateAnimation.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    dispatchOnLauncherTransitionEnd(fromView, animated, false);
+                    dispatchOnLauncherTransitionEnd(toView, animated, false);
+
+                    revealView.setVisibility(View.INVISIBLE);
+                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
+                    if (page != null) {
+                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+                    }
+                    content.setPageBackgroundsVisible(true);
+
+                    // Hide the search bar
+                    if (mSearchDropTargetBar != null) {
+                        mSearchDropTargetBar.hideSearchBar(false);
+                    }
+                }
+
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    // Prepare the position
+                    toView.bringToFront();
+                    toView.setVisibility(View.VISIBLE);
+                }
+            });
+
             boolean delayAnim = false;
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
@@ -3368,13 +3360,14 @@
                     // we waited for a layout/draw pass
                     if (mStateAnimation != stateAnimation)
                         return;
-                    setPivotsForZoom(toView, scale);
                     dispatchOnLauncherTransitionStart(fromView, animated, false);
                     dispatchOnLauncherTransitionStart(toView, animated, false);
                     LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView);
                 }
             };
             if (delayAnim) {
+                toView.bringToFront();
+                toView.setVisibility(View.VISIBLE);
                 final ViewTreeObserver observer = toView.getViewTreeObserver();
                 observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                         public void onGlobalLayout() {
@@ -3429,6 +3422,8 @@
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
         final int fadeOutDuration = res.getInteger(R.integer.config_appsCustomizeFadeOutTime);
         final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
+        final int itemsAlphaStagger =
+                res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
 
         final float scaleFactor = (float)
                 res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
@@ -3445,116 +3440,94 @@
                     toState, animated);
         }
 
-        setPivotsForZoom(fromView, scaleFactor);
         showHotseat(animated);
         if (animated) {
-            if (!material) {
-                final LauncherViewPropertyAnimator scaleAnim =
-                        new LauncherViewPropertyAnimator(fromView);
-                scaleAnim.
-                    scaleX(scaleFactor).scaleY(scaleFactor).
-                    setDuration(duration).
-                    setInterpolator(new Workspace.ZoomInInterpolator());
+            mStateAnimation = LauncherAnimUtils.createAnimatorSet();
 
-                final ObjectAnimator alphaAnim = LauncherAnimUtils
-                    .ofFloat(fromView, "alpha", 1f, 0f)
-                    .setDuration(fadeOutDuration);
-                alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator());
-                alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animation) {
-                        float t = 1f - (Float) animation.getAnimatedValue();
-                        dispatchOnLauncherTransitionStep(fromView, t);
-                        dispatchOnLauncherTransitionStep(toView, t);
-                    }
-                });
+            final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                    fromView.findViewById(R.id.apps_customize_pane_content);
 
-                mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+            final View page = content.getPageAt(content.getNextPage());
+            final View revealView = fromView.findViewById(R.id.fake_page);
 
-                dispatchOnLauncherTransitionPrepare(fromView, animated, true);
-                dispatchOnLauncherTransitionPrepare(toView, animated, true);
-                mAppsCustomizeContent.stopScrolling();
-
-                mStateAnimation.playTogether(scaleAnim, alphaAnim);
+            AppsCustomizePagedView.ContentType contentType = content.getContentType();
+            if (contentType == AppsCustomizePagedView.ContentType.Widgets) {
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
             } else {
-                mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
+            }
 
-                int width = fromView.getMeasuredWidth();
-                int height = fromView.getMeasuredHeight();
-                float revealRadius = (float) Math.sqrt((width * width) / 4 + height * height);
+            int width = revealView.getMeasuredWidth();
+            int height = revealView.getMeasuredHeight();
+            float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
 
-                AppsCustomizePagedView content = (AppsCustomizePagedView)
-                        fromView.findViewById(R.id.apps_customize_pane_content);
+            // Hide the real page background, and swap in the fake one
+            revealView.setVisibility(View.VISIBLE);
+            content.setPageBackgroundsVisible(false);
 
-                final View page = content.getPageAt(content.getNextPage());
-                View revealView = page;
+            float yDrift = height / 2f;
 
-                float yDrift = height / 2f - 400;
+            revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 
-                LauncherViewPropertyAnimator panelAlphaAndDrift =
-                        new LauncherViewPropertyAnimator(revealView);
-                revealView.setTranslationY(0);
-                revealView.setAlpha(1);
-                panelAlphaAndDrift.alpha(0)
-                    .translationY(yDrift)
-                    .setDuration(revealDuration)
-                    .setInterpolator(new LogDecelerateInterpolator(100, 0));
+            PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 0f);
+            PropertyValuesHolder panelDrift =
+                    PropertyValuesHolder.ofFloat("translationY", 0, yDrift);
+            ObjectAnimator panelAlphaAndDrift =
+                    ObjectAnimator.ofPropertyValuesHolder(revealView, panelAlpha, panelDrift);
+            panelAlphaAndDrift.setDuration(revealDuration);
 
-                mStateAnimation.play(panelAlphaAndDrift);
+            panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+            panelAlphaAndDrift.setStartDelay(itemsAlphaStagger);
 
-                if (page instanceof CellLayout) {
-                    final CellLayout cellLayout = (CellLayout) page;
-                    cellLayout.enableHardwareLayer(true);
+            mStateAnimation.play(panelAlphaAndDrift);
 
-                    final View iconsView = cellLayout.getShortcutsAndWidgets();
+            if (page != null) {
+                page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 
-                    LauncherViewPropertyAnimator iconsAlpha =
-                            new LauncherViewPropertyAnimator(iconsView);
-                    iconsAlpha.alpha(0f)
-                        .setDuration(revealDuration - 100)
-                        .setInterpolator(new LogDecelerateInterpolator(100, 0));
+                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", 0, yDrift);
+                pageDrift.setDuration(revealDuration);
+                pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                pageDrift.setStartDelay(itemsAlphaStagger);
+                mStateAnimation.play(pageDrift);
 
-                    mStateAnimation.play(iconsAlpha);
+                page.setAlpha(1f);
+                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, View.ALPHA, 1f, 0f);
+                itemsAlpha.setDuration(revealDuration);
+                itemsAlpha.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                mStateAnimation.play(itemsAlpha);
+            }
 
-                    mStateAnimation.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            cellLayout.setTranslationY(0);
-                            cellLayout.setAlpha(1f);
-                            iconsView.setAlpha(1f);
-                        }
-                    });
-                }
+            View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
+            pageIndicators.setAlpha(1f);
+            ObjectAnimator indicatorsAlpha =
+                    ObjectAnimator.ofFloat(pageIndicators, "alpha", 0f);
+            indicatorsAlpha.setDuration(revealDuration);
+            indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
+            mStateAnimation.play(indicatorsAlpha);
 
-                View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
-                final LauncherViewPropertyAnimator indicatorsAlpha =
-                        new LauncherViewPropertyAnimator(pageIndicators);
-                indicatorsAlpha.alpha(0f);
-                indicatorsAlpha.setDuration(revealDuration);
-                indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
-                mStateAnimation.play(indicatorsAlpha);
+            width = revealView.getMeasuredWidth();
 
-                width = revealView.getMeasuredWidth();
-
+            if (material) {
                 Animator reveal =
                         ViewAnimationUtils.createCircularReveal(revealView, width / 2,
                                 height / 2 + 100, revealRadius, 0f);
                 reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
                 reveal.setDuration(revealDuration);
+                reveal.setStartDelay(itemsAlphaStagger);
 
                 reveal.addListener(new AnimatorListenerAdapter() {
-                    @Override
                     public void onAnimationEnd(Animator animation) {
-                        fromView.setVisibility(View.GONE);
+                        revealView.setVisibility(View.INVISIBLE);
                     }
                 });
 
-                dispatchOnLauncherTransitionPrepare(fromView, animated, true);
-                dispatchOnLauncherTransitionPrepare(toView, animated, true);
-                mAppsCustomizeContent.stopScrolling();
-
                 mStateAnimation.play(reveal);
             }
+
+            dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+            dispatchOnLauncherTransitionPrepare(toView, animated, true);
+            mAppsCustomizeContent.stopScrolling();
+
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
             }
@@ -3568,6 +3541,12 @@
                     if (onCompleteRunnable != null) {
                         onCompleteRunnable.run();
                     }
+
+                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
+                    if (page != null) {
+                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+                    }
+                    content.setPageBackgroundsVisible(true);
                     mAppsCustomizeContent.updateCurrentPageScroll();
                 }
             });
@@ -4398,7 +4377,64 @@
         }
         final Workspace workspace = mWorkspace;
 
-        final AppWidgetProviderInfo appWidgetInfo;
+        AppWidgetProviderInfo appWidgetInfo;
+        if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) &&
+                ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
+
+            appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName);
+            if (appWidgetInfo == null) {
+                if (DEBUG_WIDGETS) {
+                    Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+                            + " belongs to component " + item.providerName
+                            + ", as the povider is null");
+                }
+                LauncherModel.deleteItemFromDatabase(this, item);
+                return;
+            }
+            // Note: This assumes that the id remap broadcast is received before this step.
+            // If that is not the case, the id remap will be ignored and user may see the
+            // click to setup view.
+            PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo, null, null);
+            pendingInfo.spanX = item.spanX;
+            pendingInfo.spanY = item.spanY;
+            pendingInfo.minSpanX = item.minSpanX;
+            pendingInfo.minSpanY = item.minSpanY;
+            Bundle options =
+                    AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo);
+
+            boolean success = false;
+            int newWidgetId = mAppWidgetHost.allocateAppWidgetId();
+            if (options != null) {
+                success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId,
+                        appWidgetInfo.provider, options);
+            } else {
+                success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId,
+                        appWidgetInfo.provider);
+            }
+
+            // TODO consider showing a permission dialog when the widget is clicked.
+            if (!success) {
+                mAppWidgetHost.deleteAppWidgetId(newWidgetId);
+                if (DEBUG_WIDGETS) {
+                    Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+                            + " belongs to component " + item.providerName
+                            + ", as the launcher is unable to bing a new widget id");
+                }
+                LauncherModel.deleteItemFromDatabase(this, item);
+                return;
+            }
+
+            item.appWidgetId = newWidgetId;
+
+            // If the widget has a configure activity, it is still needs to set it up, otherwise
+            // the widget is ready to go.
+            item.restoreStatus = (appWidgetInfo.configure == null)
+                    ? LauncherAppWidgetInfo.RESTORE_COMPLETED
+                    : LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
+
+            LauncherModel.updateItemInDatabase(this, item);
+        }
+
         if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
             final int appWidgetId = item.appWidgetId;
             appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
@@ -4409,8 +4445,9 @@
             item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
         } else {
             appWidgetInfo = null;
-            item.hostView = new LauncherAppWidgetHostView(this, false);
+            item.hostView = new PendingAppWidgetHostView(this, item.restoreStatus);
             item.hostView.updateAppWidget(null);
+            item.hostView.setOnClickListener(this);
         }
 
         item.hostView.setTag(item);
@@ -4428,6 +4465,29 @@
         }
     }
 
+    /**
+     * Restores a pending widget.
+     *
+     * @param appWidgetId The app widget id
+     * @param cellInfo The position on screen where to create the widget.
+     */
+    private void completeRestoreAppWidget(final int appWidgetId) {
+        LauncherAppWidgetHostView view = mWorkspace.getWidgetForAppWidgetId(appWidgetId);
+        if ((view == null) || !(view instanceof PendingAppWidgetHostView)) {
+            Log.e(TAG, "Widget update called, when the widget no longer exists.");
+            return;
+        }
+
+        PendingAppWidgetHostView pendingView = (PendingAppWidgetHostView) view;
+        pendingView.setStatus(LauncherAppWidgetInfo.RESTORE_COMPLETED);
+
+        LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) pendingView.getTag();
+        info.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+
+        mWorkspace.reinflateWidgetsIfNecessary();
+        LauncherModel.updateItemInDatabase(this, info);
+    }
+
     public void onPageBoundSynchronously(int page) {
         mSynchronouslyBoundPages.add(page);
     }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 7eb0052..e39727b 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -18,7 +18,6 @@
 
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
-import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -32,36 +31,22 @@
  * {@inheritDoc}
  */
 public class LauncherAppWidgetHostView extends AppWidgetHostView implements TouchCompleteListener {
+
+    LayoutInflater mInflater;
+
     private CheckLongPressHelper mLongPressHelper;
-    private LayoutInflater mInflater;
     private Context mContext;
     private int mPreviousOrientation;
     private DragLayer mDragLayer;
 
     private float mSlop;
 
-    private boolean mWidgetReady;
-
     public LauncherAppWidgetHostView(Context context) {
-        this(context, true);
-    }
-
-    public LauncherAppWidgetHostView(Context context, boolean widgetReady) {
         super(context);
         mContext = context;
         mLongPressHelper = new CheckLongPressHelper(this);
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mDragLayer = ((Launcher) context).getDragLayer();
-        mWidgetReady = widgetReady;
-    }
-
-    @Override
-    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
-            int maxHeight) {
-        // If the widget is not yet ready, the app widget size cannot be updated.
-        if (mWidgetReady) {
-            super.updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight);
-        }
     }
 
     @Override
@@ -70,22 +55,14 @@
     }
 
     @Override
-    protected View getDefaultView() {
-        if (mWidgetReady) {
-            return super.getDefaultView();
-        } else {
-            return mInflater.inflate(R.layout.appwidget_not_ready, this, false);
-        }
-    }
-
-    @Override
     public void updateAppWidget(RemoteViews remoteViews) {
         // Store the orientation in which the widget was inflated
         mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
         super.updateAppWidget(remoteViews);
     }
 
-    public boolean orientationChangedSincedInflation() {
+    public boolean isReinflateRequired() {
+        // Re-inflate is required if the orientation has changed since last inflated.
         int orientation = mContext.getResources().getConfiguration().orientation;
         if (mPreviousOrientation != orientation) {
            return true;
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index b3ac12b..c1535ab 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -33,12 +33,17 @@
     /**
      * This is set during the package backup creation.
      */
-    public static final int RESTORE_REMAP_PENDING = 1;
+    public static final int FLAG_ID_NOT_VALID = 1;
 
     /**
-     * Widget provider is not yet installed.
+     * Indicates that the provider is not available yet.
      */
-    public static final int RESTORE_PROVIDER_PENDING = 2;
+    public static final int FLAG_PROVIDER_NOT_READY = 2;
+
+    /**
+     * Indicates that the widget UI is not yet ready, and user needs to set it up again.
+     */
+    public static final int FLAG_UI_NOT_READY = 4;
 
     /**
      * Indicates that the widget hasn't been instantiated yet.
@@ -89,6 +94,7 @@
         super.onAddToDatabase(context, values);
         values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString());
+        values.put(LauncherSettings.Favorites.RESTORED, restoreStatus);
     }
 
     /**
@@ -121,6 +127,10 @@
     }
 
     public final boolean isWidgetIdValid() {
-        return restoreStatus != RESTORE_REMAP_PENDING;
+        return (restoreStatus & FLAG_ID_NOT_VALID) == 0;
+    }
+
+    public final boolean hasRestoreFlag(int flag) {
+        return (restoreStatus & flag) == flag;
     }
 }
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 5663314..aecf9b0 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -874,20 +874,25 @@
             values.put(Favorites.INTENT, favorite.intent);
         }
         values.put(Favorites.ITEM_TYPE, favorite.itemType);
-        if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
-            if (!TextUtils.isEmpty(favorite.appWidgetProvider)) {
-                values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider);
-            }
-            values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId);
-        }
 
         UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
         long userSerialNumber =
                 UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle);
         values.put(LauncherSettings.Favorites.PROFILE_ID, userSerialNumber);
 
-        // Let LauncherModel know we've been here.
-        values.put(LauncherSettings.Favorites.RESTORED, 1);
+        if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+            if (!TextUtils.isEmpty(favorite.appWidgetProvider)) {
+                values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider);
+            }
+            values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId);
+            values.put(LauncherSettings.Favorites.RESTORED,
+                    LauncherAppWidgetInfo.FLAG_ID_NOT_VALID |
+                    LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY |
+                    LauncherAppWidgetInfo.FLAG_UI_NOT_READY);
+        } else {
+            // Let LauncherModel know we've been here.
+            values.put(LauncherSettings.Favorites.RESTORED, 1);
+        }
 
         return values;
     }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 86edaef..5c668d6 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -2128,47 +2128,59 @@
                                 int appWidgetId = c.getInt(appWidgetIdIndex);
                                 String savedProvider = c.getString(appWidgetProviderIndex);
                                 id = c.getLong(idIndex);
+                                final ComponentName component =
+                                        ComponentName.unflattenFromString(savedProvider);
 
                                 final int restoreStatus = c.getInt(restoredIndex);
-                                final boolean restorePending = Utilities.isLmp()
-                                        && (restoreStatus ==
-                                            LauncherAppWidgetInfo.RESTORE_REMAP_PENDING);
-                                final boolean providerPending = Utilities.isLmp()
-                                        && (restoreStatus ==
-                                            LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING);
+                                final boolean isIdValid = (restoreStatus &
+                                        LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;
 
-                                // Do not try to get the provider if restore is pending, as the
-                                // widget id is invalid, and it might point to some other provider.
-                                final AppWidgetProviderInfo provider = restorePending ? null
-                                        : widgets.getAppWidgetInfo(appWidgetId);
-                                boolean providerValid = isValidProvider(provider);
+                                final boolean wasProviderReady = (restoreStatus &
+                                        LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
 
-                                // Skip provider check,
-                                //    1. when the widget id re-map is pending
-                                //    2. provider is pending install for a restored widget
-                                if (!isSafeMode && !providerPending && !restorePending
-                                        && !providerValid) {
+                                final AppWidgetProviderInfo provider = isIdValid
+                                        ? widgets.getAppWidgetInfo(appWidgetId)
+                                        : findAppWidgetProviderInfoWithComponent(context, component);
+
+                                final boolean isProviderReady = isValidProvider(provider);
+                                if (!isSafeMode && wasProviderReady && !isProviderReady) {
                                     String log = "Deleting widget that isn't installed anymore: "
-                                        + "id=" + id + " appWidgetId=" + appWidgetId;
+                                            + "id=" + id + " appWidgetId=" + appWidgetId;
                                     Log.e(TAG, log);
                                     Launcher.addDumpLog(TAG, log, false);
                                     itemsToRemove.add(id);
                                 } else {
-                                    if (providerValid) {
+                                    if (isProviderReady) {
                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
                                                 provider.provider);
                                         int[] minSpan =
                                                 Launcher.getMinSpanForWidget(context, provider);
                                         appWidgetInfo.minSpanX = minSpan[0];
                                         appWidgetInfo.minSpanY = minSpan[1];
+
+                                        int status = restoreStatus;
+                                        if (!wasProviderReady) {
+                                            // If provider was not previously ready, update the
+                                            // status and UI flag.
+
+                                            // Id would be valid only if the widget restore broadcast was received.
+                                            if (isIdValid) {
+                                                status = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+                                            } else {
+                                                status &= ~LauncherAppWidgetInfo
+                                                        .FLAG_PROVIDER_NOT_READY;
+                                            }
+                                        }
+                                        appWidgetInfo.restoreStatus = status;
                                     } else {
                                         Log.v(TAG, "Widget restore pending id=" + id
                                                 + " appWidgetId=" + appWidgetId
                                                 + " status =" + restoreStatus);
                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
-                                                ComponentName.unflattenFromString(savedProvider));
+                                                component);
                                         appWidgetInfo.restoreStatus = restoreStatus;
                                     }
+
                                     appWidgetInfo.id = id;
                                     appWidgetInfo.screenId = c.getInt(screenIndex);
                                     appWidgetInfo.cellX = c.getInt(cellXIndex);
@@ -2195,15 +2207,15 @@
                                         break;
                                     }
 
-                                    if (providerValid) {
+                                    if (isProviderReady) {
                                         String providerName = provider.provider.flattenToString();
-
-                                        if (!providerName.equals(savedProvider) || providerPending) {
+                                        if (!providerName.equals(savedProvider) ||
+                                                (appWidgetInfo.restoreStatus != restoreStatus)) {
                                             ContentValues values = new ContentValues();
                                             values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
                                                     providerName);
                                             values.put(LauncherSettings.Favorites.RESTORED,
-                                                    LauncherAppWidgetInfo.RESTORE_COMPLETED);
+                                                    appWidgetInfo.restoreStatus);
                                             String where = BaseColumns._ID + "= ?";
                                             String[] args = {Long.toString(id)};
                                             contentResolver.update(contentUri, values, where, args);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 1037d98..90a6b15 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -152,16 +152,11 @@
     protected int mTouchState = TOUCH_STATE_REST;
     protected boolean mForceScreenScrolled = false;
 
-
     protected OnLongClickListener mLongClickListener;
 
     protected int mTouchSlop;
     private int mPagingTouchSlop;
     private int mMaximumVelocity;
-    protected int mPageLayoutPaddingTop;
-    protected int mPageLayoutPaddingBottom;
-    protected int mPageLayoutPaddingLeft;
-    protected int mPageLayoutPaddingRight;
     protected int mPageLayoutWidthGap;
     protected int mPageLayoutHeightGap;
     protected int mCellCountX = 0;
@@ -283,14 +278,6 @@
         TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.PagedView, defStyle, 0);
 
-        mPageLayoutPaddingTop = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingTop, 0);
-        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingBottom, 0);
-        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingLeft, 0);
-        mPageLayoutPaddingRight = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingRight, 0);
         mPageLayoutWidthGap = a.getDimensionPixelSize(
                 R.styleable.PagedView_pageLayoutWidthGap, 0);
         mPageLayoutHeightGap = a.getDimensionPixelSize(
@@ -339,8 +326,9 @@
 
         // Hook up the page indicator
         ViewGroup parent = (ViewGroup) getParent();
+        ViewGroup grandParent = (ViewGroup) parent.getParent();
         if (mPageIndicator == null && mPageIndicatorViewId > -1) {
-            mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId);
+            mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId);
             mPageIndicator.removeAllMarkers(mAllowPagedViewAnimations);
 
             ArrayList<PageIndicator.PageMarkerResources> markers =
diff --git a/src/com/android/launcher3/PagedViewGridLayout.java b/src/com/android/launcher3/PagedViewGridLayout.java
index b286861..f69fa56 100644
--- a/src/com/android/launcher3/PagedViewGridLayout.java
+++ b/src/com/android/launcher3/PagedViewGridLayout.java
@@ -56,18 +56,6 @@
         }
     }
 
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // PagedView currently has issues with different-sized pages since it calculates the
-        // offset of each page to scroll to before it updates the actual size of each page
-        // (which can change depending on the content if the contents aren't a fixed size).
-        // We work around this by having a minimum size on each widget page).
-        int widthSpecSize = Math.min(getSuggestedMinimumWidth(),
-                MeasureSpec.getSize(widthMeasureSpec));
-        int widthSpecMode = MeasureSpec.EXACTLY;
-        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
-                heightMeasureSpec);
-    }
-
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
new file mode 100644
index 0000000..048e9f8
--- /dev/null
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -0,0 +1,78 @@
+package com.android.launcher3;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener {
+
+    int mRestoreStatus;
+
+    private TextView mDefaultView;
+    private OnClickListener mClickListener;
+
+    public PendingAppWidgetHostView(Context context, int restoreStatus) {
+        super(context);
+        mRestoreStatus = restoreStatus;
+    }
+
+    @Override
+    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
+            int maxHeight) {
+        // No-op
+    }
+
+    @Override
+    protected View getDefaultView() {
+        if (mDefaultView == null) {
+            mDefaultView = (TextView) mInflater.inflate(R.layout.appwidget_not_ready, this, false);
+            mDefaultView.setOnClickListener(this);
+            applyState();
+        }
+        return mDefaultView;
+    }
+
+    @Override
+    public void setOnClickListener(OnClickListener l) {
+        mClickListener = l;
+    }
+
+    public void setStatus(int status) {
+        if (mRestoreStatus != status) {
+            mRestoreStatus = status;
+            applyState();
+        }
+    }
+
+    @Override
+    public boolean isReinflateRequired() {
+        // Re inflate is required if the the widget is restored.
+        return mRestoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED;
+    }
+
+    private void applyState() {
+        if (mDefaultView != null) {
+            if (isReadyForClickSetup()) {
+                mDefaultView.setText(R.string.gadget_setup_text);
+            } else {
+                mDefaultView.setText(R.string.gadget_pending_text);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        // AppWidgetHostView blocks all click events on the root view. Instead handle click events
+        // on the content and pass it along.
+        if (mClickListener != null) {
+            mClickListener.onClick(this);
+        }
+    }
+
+    public boolean isReadyForClickSetup() {
+        return (mRestoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0
+                && (mRestoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0;
+    }
+}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index c1bbbe0..e852ec7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -30,8 +30,6 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
@@ -49,7 +47,6 @@
 import android.os.AsyncTask;
 import android.os.IBinder;
 import android.os.Parcelable;
-import android.provider.BaseColumns;
 import android.support.v4.view.ViewCompat;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -75,6 +72,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -212,7 +210,6 @@
     private final int[] mTempXY = new int[2];
     private int[] mTempVisiblePagesRange = new int[2];
     private boolean mOverscrollTransformsSet;
-    private float mLastOverscrollPivotX;
     public static final int DRAG_BITMAP_PADDING = 2;
     private boolean mWorkspaceFadeInAdjacentScreens;
 
@@ -1119,10 +1116,10 @@
             for (int j = 0; j < itemCount; j++) {
                 View v = swc.getChildAt(j);
 
-                if (v.getTag() instanceof LauncherAppWidgetInfo) {
+                if (v != null  && v.getTag() instanceof LauncherAppWidgetInfo) {
                     LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
                     LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
-                    if (lahv != null && lahv.orientationChangedSincedInflation()) {
+                    if (lahv != null && lahv.isReinflateRequired()) {
                         mLauncher.removeAppWidget(info);
                         // Remove the current widget which is inflated with the wrong orientation
                         cl.removeView(lahv);
@@ -1694,20 +1691,13 @@
 
             final boolean isLeftPage = mOverScrollX < 0;
             index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex;
-            pivotX = isLeftPage ? rightBiasedPivot : leftBiasedPivot;
 
             CellLayout cl = (CellLayout) getChildAt(index);
             float scrollProgress = getScrollProgress(screenCenter, cl, index);
             cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage);
-            float rotation = -WORKSPACE_OVERSCROLL_ROTATION * scrollProgress;
-            cl.setRotationY(rotation);
 
-            if (!mOverscrollTransformsSet || Float.compare(mLastOverscrollPivotX, pivotX) != 0) {
+            if (!mOverscrollTransformsSet) {
                 mOverscrollTransformsSet = true;
-                mLastOverscrollPivotX = pivotX;
-                cl.setCameraDistance(mDensity * mCameraDistance);
-                cl.setPivotX(cl.getMeasuredWidth() * pivotX);
-                cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
                 cl.setOverscrollTransformsDirty(true);
             }
         } else {
@@ -3258,7 +3248,6 @@
         LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
 
-        Resources res = launcher.getResources();
         Display display = launcher.getWindowManager().getDefaultDisplay();
         Point smallestSize = new Point();
         Point largestSize = new Point();
@@ -4591,29 +4580,43 @@
     }
 
     public Folder getFolderForTag(final Object tag) {
-        final Folder[] value = new Folder[1];
-        mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
+        return (Folder) getFirstMatch(new ItemOperator() {
+
             @Override
             public boolean evaluate(ItemInfo info, View v, View parent) {
-                if (v instanceof Folder) {
-                    Folder f = (Folder) v;
-                    if (f.getInfo() == tag && f.getInfo().opened) {
-                        value[0] = f;
-                        return true;
-                    }
-                }
-                return false;
+                return (v instanceof Folder) && (((Folder) v).getInfo() == tag)
+                        && ((Folder) v).getInfo().opened;
             }
         });
-        return value[0];
     }
 
     public View getViewForTag(final Object tag) {
+        return getFirstMatch(new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                return info == tag;
+            }
+        });
+    }
+
+    public LauncherAppWidgetHostView getWidgetForAppWidgetId(final int appWidgetId) {
+        return (LauncherAppWidgetHostView) getFirstMatch(new ItemOperator() {
+
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                return (info instanceof LauncherAppWidgetInfo) &&
+                        ((LauncherAppWidgetInfo) info).appWidgetId == appWidgetId;
+            }
+        });
+    }
+
+    private View getFirstMatch(final ItemOperator operator) {
         final View[] value = new View[1];
         mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
             @Override
             public boolean evaluate(ItemInfo info, View v, View parent) {
-                if (v.getTag() == tag) {
+                if (operator.evaluate(info, v, parent)) {
                     value[0] = v;
                     return true;
                 }
@@ -4895,7 +4898,7 @@
     }
 
     private void restorePendingWidgets(final Set<String> installedPackaged) {
-        final ContentResolver contentResolver = getContext().getContentResolver();
+        final AtomicBoolean widgetsChanged = new AtomicBoolean(false);
         // Iterate non recursively as widgets can't be inside a folder.
         mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
 
@@ -4903,22 +4906,21 @@
             public boolean evaluate(ItemInfo info, View v, View parent) {
                 if (info instanceof LauncherAppWidgetInfo) {
                     LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
-                    if (widgetInfo.restoreStatus == LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING
+                    if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
                             && installedPackaged.contains(widgetInfo.providerName.getPackageName())) {
-                        // Package installed. Update pending widgets.
-                        ContentValues values = new ContentValues();
-                        values.put(LauncherSettings.Favorites.RESTORED,
-                                LauncherAppWidgetInfo.RESTORE_COMPLETED);
-                        String where = BaseColumns._ID + "= ?";
-                        String[] args = {Long.toString(widgetInfo.id)};
-                        contentResolver.update(LauncherSettings.Favorites.CONTENT_URI,
-                                values, where, args);
+                        widgetsChanged.set(true);
                     }
                 }
                 // process all the widget
                 return false;
             }
         });
+        if (widgetsChanged.get()) {
+            // Reload layout and update widget status
+            // TODO instead of full reload, just update the specific widgets
+            getContext().getContentResolver()
+                .notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
+        }
     }
 
     private void moveToScreen(int page, boolean animate) {
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index ad6f78e..0ad824b 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -48,7 +48,12 @@
 
     @Override
     public Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user) {
-        return mUserManager.getBadgedIconForUser(unbadged, user.getUser());
+        try {
+            // STOPSHIP(mokani): Clean this up.
+            return mUserManager.getBadgedIconForUser(unbadged, user.getUser());
+        } catch (Throwable t) {
+            return unbadged;
+        }
     }
 
     @Override